Skip to content
This repository was archived by the owner on May 12, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 29 additions & 133 deletions lightbug_http/address.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -372,10 +372,10 @@ fn get_ip_address(
try:
result = getaddrinfo(host, service, hints)
except getaddrinfo_err:
raise getaddrinfo_err
raise GetIPAddressError(getaddrinfo_err)

if not result.unsafe_ptr()[].ai_addr:
raise GetaddrinfoNullAddrError()
raise GetIPAddressError(GetaddrinfoNullAddrError())

# extend result's lifetime to avoid invalid access of pointer, it'd get freed early
return (
Expand All @@ -396,10 +396,10 @@ fn get_ip_address(
try:
result = getaddrinfo(host, service, hints)
except getaddrinfo_err:
raise getaddrinfo_err
raise GetIPAddressError(getaddrinfo_err)

if not result.unsafe_ptr()[].ai_addr:
raise GetaddrinfoNullAddrError()
raise GetIPAddressError(GetaddrinfoNullAddrError())

return (
result.unsafe_ptr()[]
Expand Down Expand Up @@ -561,125 +561,21 @@ struct GetaddrinfoError(CustomError, TrivialRegisterPassable):



@fieldwise_init
struct GetIPAddressError(Movable, Stringable, Writable):
"""Typed error variant for get_ip_address() function."""

comptime type = Variant[GetaddrinfoError, GetaddrinfoNullAddrError]
var value: Self.type

@implicit
fn __init__(out self, value: GetaddrinfoError):
self.value = value

@implicit
fn __init__(out self, value: GetaddrinfoNullAddrError):
self.value = value

fn write_to[W: Writer, //](self, mut writer: W):
if self.value.isa[GetaddrinfoError]():
writer.write(self.value[GetaddrinfoError])
elif self.value.isa[GetaddrinfoNullAddrError]():
writer.write(self.value[GetaddrinfoNullAddrError])

fn isa[T: AnyType](self) -> Bool:
return self.value.isa[T]()

fn __getitem__[T: AnyType](self) -> ref [self.value] T:
return self.value[T]

fn __str__(self) -> String:
return String.write(self)


@fieldwise_init
struct ParseError(Movable, Stringable, Writable):
"""Typed error variant for address parsing functions."""

comptime type = Variant[
ParseEmptyAddressError,
ParseMissingClosingBracketError,
ParseMissingPortError,
ParseUnexpectedBracketError,
ParseEmptyPortError,
ParseInvalidPortNumberError,
ParsePortOutOfRangeError,
ParseMissingSeparatorError,
ParseTooManyColonsError,
ParseIPProtocolPortError,
]
var value: Self.type

@implicit
fn __init__(out self, value: ParseEmptyAddressError):
self.value = value

@implicit
fn __init__(out self, value: ParseMissingClosingBracketError):
self.value = value

@implicit
fn __init__(out self, value: ParseMissingPortError):
self.value = value

@implicit
fn __init__(out self, value: ParseUnexpectedBracketError):
self.value = value

@implicit
fn __init__(out self, value: ParseEmptyPortError):
self.value = value

@implicit
fn __init__(out self, value: ParseInvalidPortNumberError):
self.value = value
comptime GetIPAddressError = Variant[GetaddrinfoError, GetaddrinfoNullAddrError]

@implicit
fn __init__(out self, value: ParsePortOutOfRangeError):
self.value = value

@implicit
fn __init__(out self, value: ParseMissingSeparatorError):
self.value = value

@implicit
fn __init__(out self, value: ParseTooManyColonsError):
self.value = value

@implicit
fn __init__(out self, value: ParseIPProtocolPortError):
self.value = value

fn write_to[W: Writer, //](self, mut writer: W):
if self.value.isa[ParseEmptyAddressError]():
writer.write(self.value[ParseEmptyAddressError])
elif self.value.isa[ParseMissingClosingBracketError]():
writer.write(self.value[ParseMissingClosingBracketError])
elif self.value.isa[ParseMissingPortError]():
writer.write(self.value[ParseMissingPortError])
elif self.value.isa[ParseUnexpectedBracketError]():
writer.write(self.value[ParseUnexpectedBracketError])
elif self.value.isa[ParseEmptyPortError]():
writer.write(self.value[ParseEmptyPortError])
elif self.value.isa[ParseInvalidPortNumberError]():
writer.write(self.value[ParseInvalidPortNumberError])
elif self.value.isa[ParsePortOutOfRangeError]():
writer.write(self.value[ParsePortOutOfRangeError])
elif self.value.isa[ParseMissingSeparatorError]():
writer.write(self.value[ParseMissingSeparatorError])
elif self.value.isa[ParseTooManyColonsError]():
writer.write(self.value[ParseTooManyColonsError])
elif self.value.isa[ParseIPProtocolPortError]():
writer.write(self.value[ParseIPProtocolPortError])

fn isa[T: AnyType](self) -> Bool:
return self.value.isa[T]()

fn __getitem__[T: AnyType](self) -> ref [self.value] T:
return self.value[T]

fn __str__(self) -> String:
return String.write(self)
comptime ParseError = Variant[
ParseEmptyAddressError,
ParseMissingClosingBracketError,
ParseMissingPortError,
ParseUnexpectedBracketError,
ParseEmptyPortError,
ParseInvalidPortNumberError,
ParsePortOutOfRangeError,
ParseMissingSeparatorError,
ParseTooManyColonsError,
ParseIPProtocolPortError,
]


fn parse_ipv6_bracketed_address[
Expand All @@ -695,14 +591,14 @@ fn parse_ipv6_bracketed_address[

var end_bracket_index = address.find("]")
if end_bracket_index == -1:
raise ParseMissingClosingBracketError()
raise ParseError(ParseMissingClosingBracketError())

if end_bracket_index + 1 == len(address):
raise ParseMissingPortError()
raise ParseError(ParseMissingPortError())

var colon_index = end_bracket_index + 1
if address[colon_index : colon_index + 1] != ":":
raise ParseMissingPortError()
raise ParseError(ParseMissingPortError())

return address[1:end_bracket_index], UInt16(end_bracket_index + 1)

Expand All @@ -719,24 +615,24 @@ fn validate_no_brackets[
segment = address[Int(start_idx) : Int(end_idx.value())]

if segment.find("[") != -1:
raise ParseUnexpectedBracketError()
raise ParseError(ParseUnexpectedBracketError())
if segment.find("]") != -1:
raise ParseUnexpectedBracketError()
raise ParseError(ParseUnexpectedBracketError())


fn parse_port[origin: ImmutOrigin](port_str: StringSlice[origin]) raises ParseError -> UInt16:
"""Parse and validate port number."""
if port_str == AddressConstants.EMPTY:
raise ParseEmptyPortError()
raise ParseError(ParseEmptyPortError())

var port: Int
try:
port = Int(String(port_str))
except conversion_err:
raise ParseInvalidPortNumberError()
raise ParseError(ParseInvalidPortNumberError())

if port < MIN_PORT or port > MAX_PORT:
raise ParsePortOutOfRangeError()
raise ParseError(ParsePortOutOfRangeError())

return UInt16(port)

Expand Down Expand Up @@ -765,7 +661,7 @@ fn parse_address[
Tuple containing the host and port.
"""
if address == AddressConstants.EMPTY:
raise ParseEmptyAddressError()
raise ParseError(ParseEmptyAddressError())

if address == AddressConstants.LOCALHOST:

Expand All @@ -781,13 +677,13 @@ fn parse_address[
return HostPort(String(address), DEFAULT_IP_PORT)

if address.find(":") != -1:
raise ParseIPProtocolPortError()
raise ParseError(ParseIPProtocolPortError())

return HostPort(String(address), DEFAULT_IP_PORT)

var colon_index = address.rfind(":")
if colon_index == -1:
raise ParseMissingSeparatorError()
raise ParseError(ParseMissingSeparatorError())

var host: StringSlice[origin]
var port: UInt16
Expand All @@ -802,7 +698,7 @@ fn parse_address[
else:
host = address[:colon_index]
if host.find(":") != -1:
raise ParseTooManyColonsError()
raise ParseError(ParseTooManyColonsError())

port = parse_port(address[colon_index + 1 :])
if host == AddressConstants.LOCALHOST:
Expand Down
80 changes: 9 additions & 71 deletions lightbug_http/c/network.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -41,72 +41,10 @@ struct InetPtonInvalidAddressError(CustomError, TrivialRegisterPassable):
return Self.message


@fieldwise_init
struct InetNtopError(Movable, Stringable, Writable):
"""Typed error variant for inet_ntop() function."""

comptime type = Variant[InetNtopEAFNOSUPPORTError, InetNtopENOSPCError, Error]
var value: Self.type

@implicit
fn __init__(out self, value: InetNtopEAFNOSUPPORTError):
self.value = value

@implicit
fn __init__(out self, value: InetNtopENOSPCError):
self.value = value

@implicit
fn __init__(out self, var value: Error):
self.value = value^

fn write_to[W: Writer, //](self, mut writer: W):
if self.value.isa[InetNtopEAFNOSUPPORTError]():
writer.write(self.value[InetNtopEAFNOSUPPORTError])
elif self.value.isa[InetNtopENOSPCError]():
writer.write(self.value[InetNtopENOSPCError])
elif self.value.isa[Error]():
writer.write(self.value[Error])

fn isa[T: AnyType](self) -> Bool:
return self.value.isa[T]()

fn __getitem__[T: AnyType](self) -> ref [self.value] T:
return self.value[T]

fn __str__(self) -> String:
return String.write(self)
comptime InetNtopError = Variant[InetNtopEAFNOSUPPORTError, InetNtopENOSPCError, Error]


@fieldwise_init
struct InetPtonError(Movable, Stringable, Writable):
"""Typed error variant for inet_pton() function."""

comptime type = Variant[InetPtonInvalidAddressError, Error]
var value: Self.type

@implicit
fn __init__(out self, value: InetPtonInvalidAddressError):
self.value = value

@implicit
fn __init__(out self, var value: Error):
self.value = value^

fn write_to[W: Writer, //](self, mut writer: W):
if self.value.isa[InetPtonInvalidAddressError]():
writer.write(self.value[InetPtonInvalidAddressError])
elif self.value.isa[Error]():
writer.write(self.value[Error])

fn isa[T: AnyType](self) -> Bool:
return self.value.isa[T]()

fn __getitem__[T: AnyType](self) -> ref [self.value] T:
return self.value[T]

fn __str__(self) -> String:
return String.write(self)
comptime InetPtonError = Variant[InetPtonInvalidAddressError, Error]


fn htonl(hostlong: c_uint) -> c_uint:
Expand Down Expand Up @@ -394,14 +332,14 @@ fn inet_ntop[
if not result:
var errno = get_errno()
if errno == errno.EAFNOSUPPORT:
raise InetNtopEAFNOSUPPORTError()
raise InetNtopError(InetNtopEAFNOSUPPORTError())
elif errno == errno.ENOSPC:
raise InetNtopENOSPCError()
raise InetNtopError(InetNtopENOSPCError())
else:
raise Error(
raise InetNtopError(Error(
"inet_ntop Error: An error occurred while converting the address. Error code: ",
errno,
)
))

return String(unsafe_from_utf8_ptr=dst.unsafe_ptr())

Expand Down Expand Up @@ -472,12 +410,12 @@ fn inet_pton[address_family: AddressFamily](var src: String) raises InetPtonErro

var result = _inet_pton(address_family.value, src.as_c_string_slice().unsafe_ptr(), ip_buffer)
if result == 0:
raise InetPtonInvalidAddressError()
raise InetPtonError(InetPtonInvalidAddressError())
elif result == -1:
var errno = get_errno()
raise Error(
raise InetPtonError(Error(
"inet_pton Error: An error occurred while converting the address. Error code: ",
errno,
)
))

return ip_buffer.bitcast[c_uint]().take_pointee()
Loading