From 4af579a2ee2eee22e1d5942324c894bc4f6063aa Mon Sep 17 00:00:00 2001 From: Val Date: Sat, 14 Sep 2024 17:11:04 +0200 Subject: [PATCH] add arm64 build --- .github/workflows/publish.yml | 1 + external/__init__.mojo | 0 external/libc.mojo | 993 --------------------------------- external/morrow/__init__.mojo | 5 - external/morrow/_libc.mojo | 93 --- external/morrow/_py.mojo | 11 - external/morrow/constants.mojo | 62 -- external/morrow/formatter.mojo | 185 ------ external/morrow/morrow.mojo | 353 ------------ external/morrow/timedelta.mojo | 181 ------ external/morrow/timezone.mojo | 76 --- external/morrow/util.mojo | 64 --- recipes/recipe.yaml | 1 + 13 files changed, 2 insertions(+), 2023 deletions(-) delete mode 100644 external/__init__.mojo delete mode 100644 external/libc.mojo delete mode 100644 external/morrow/__init__.mojo delete mode 100644 external/morrow/_libc.mojo delete mode 100644 external/morrow/_py.mojo delete mode 100644 external/morrow/constants.mojo delete mode 100644 external/morrow/formatter.mojo delete mode 100644 external/morrow/morrow.mojo delete mode 100644 external/morrow/timedelta.mojo delete mode 100644 external/morrow/timezone.mojo delete mode 100644 external/morrow/util.mojo diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index be3113a6..2245947c 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -13,6 +13,7 @@ jobs: matrix: include: - { target: linux-64, os: ubuntu-latest } + - { target: osx-arm64, os: macos-14 } fail-fast: false runs-on: ${{ matrix.os }} timeout-minutes: 5 diff --git a/external/__init__.mojo b/external/__init__.mojo deleted file mode 100644 index e69de29b..00000000 diff --git a/external/libc.mojo b/external/libc.mojo deleted file mode 100644 index 43ce1350..00000000 --- a/external/libc.mojo +++ /dev/null @@ -1,993 +0,0 @@ -from utils import StaticTuple -from sys.ffi import external_call -from sys.info import sizeof -from memory import memcpy -from lightbug_http.io.bytes import Bytes -alias IPPROTO_IPV6 = 41 -alias IPV6_V6ONLY = 26 -alias EPROTONOSUPPORT = 93 - -# Adapted from https://github.com/gabrieldemarmiesse/mojo-stdlib-extensions/ . Huge thanks to Gabriel! - -alias FD_STDIN: c_int = 0 -alias FD_STDOUT: c_int = 1 -alias FD_STDERR: c_int = 2 - -alias SUCCESS = 0 -alias GRND_NONBLOCK: UInt8 = 1 - -alias char_UnsafePointer = UnsafePointer[c_char] - -# Adapted from https://github.com/crisadamo/mojo-Libc . Huge thanks to Cristian! -# C types -alias c_void = UInt8 -alias c_char = UInt8 -alias c_schar = Int8 -alias c_uchar = UInt8 -alias c_short = Int16 -alias c_ushort = UInt16 -alias c_int = Int32 -alias c_uint = UInt32 -alias c_long = Int64 -alias c_ulong = UInt64 -alias c_float = Float32 -alias c_double = Float64 - -# `Int` is known to be machine's width -alias c_size_t = Int -alias c_ssize_t = Int - -alias ptrdiff_t = Int64 -alias intptr_t = Int64 -alias uintptr_t = UInt64 - - -# --- ( error.h Constants )----------------------------------------------------- -alias EPERM = 1 -alias ENOENT = 2 -alias ESRCH = 3 -alias EINTR = 4 -alias EIO = 5 -alias ENXIO = 6 -alias E2BIG = 7 -alias ENOEXEC = 8 -alias EBADF = 9 -alias ECHILD = 10 -alias EAGAIN = 11 -alias ENOMEM = 12 -alias EACCES = 13 -alias EFAULT = 14 -alias ENOTBLK = 15 -alias EBUSY = 16 -alias EEXIST = 17 -alias EXDEV = 18 -alias ENODEV = 19 -alias ENOTDIR = 20 -alias EISDIR = 21 -alias EINVAL = 22 -alias ENFILE = 23 -alias EMFILE = 24 -alias ENOTTY = 25 -alias ETXTBSY = 26 -alias EFBIG = 27 -alias ENOSPC = 28 -alias ESPIPE = 29 -alias EROFS = 30 -alias EMLINK = 31 -alias EPIPE = 32 -alias EDOM = 33 -alias ERANGE = 34 -alias EWOULDBLOCK = EAGAIN - - -fn to_char_ptr(s: String) -> UnsafePointer[c_char]: - """Only ASCII-based strings.""" - var ptr = UnsafePointer[c_char]().alloc(len(s)) - for i in range(len(s)): - ptr[i] = ord(s[i]) - return ptr - -fn to_char_ptr(s: Bytes) -> UnsafePointer[c_char]: - var ptr = UnsafePointer[c_char]().alloc(len(s)) - for i in range(len(s)): - ptr[i] = int(s[i]) - return ptr - -fn c_charptr_to_string(s: UnsafePointer[c_char]) -> String: - return String(s.bitcast[UInt8](), strlen(s)) - - -fn cftob(val: c_int) -> Bool: - """Convert C-like failure (-1) to Bool.""" - return rebind[Bool](val > 0) - - -# --- ( Network Related Constants )--------------------------------------------- -alias sa_family_t = c_ushort -alias socklen_t = c_uint -alias in_addr_t = c_uint -alias in_port_t = c_ushort - -# Address Family Constants -alias AF_UNSPEC = 0 -alias AF_UNIX = 1 -alias AF_LOCAL = AF_UNIX -alias AF_INET = 2 -alias AF_AX25 = 3 -alias AF_IPX = 4 -alias AF_APPLETALK = 5 -alias AF_NETROM = 6 -alias AF_BRIDGE = 7 -alias AF_ATMPVC = 8 -alias AF_X25 = 9 -alias AF_INET6 = 10 -alias AF_ROSE = 11 -alias AF_DECnet = 12 -alias AF_NETBEUI = 13 -alias AF_SECURITY = 14 -alias AF_KEY = 15 -alias AF_NETLINK = 16 -alias AF_ROUTE = AF_NETLINK -alias AF_PACKET = 17 -alias AF_ASH = 18 -alias AF_ECONET = 19 -alias AF_ATMSVC = 20 -alias AF_RDS = 21 -alias AF_SNA = 22 -alias AF_IRDA = 23 -alias AF_PPPOX = 24 -alias AF_WANPIPE = 25 -alias AF_LLC = 26 -alias AF_CAN = 29 -alias AF_TIPC = 30 -alias AF_BLUETOOTH = 31 -alias AF_IUCV = 32 -alias AF_RXRPC = 33 -alias AF_ISDN = 34 -alias AF_PHONET = 35 -alias AF_IEEE802154 = 36 -alias AF_CAIF = 37 -alias AF_ALG = 38 -alias AF_NFC = 39 -alias AF_VSOCK = 40 -alias AF_KCM = 41 -alias AF_QIPCRTR = 42 -alias AF_MAX = 43 - -alias PF_UNSPEC = AF_UNSPEC -alias PF_UNIX = AF_UNIX -alias PF_LOCAL = AF_LOCAL -alias PF_INET = AF_INET -alias PF_AX25 = AF_AX25 -alias PF_IPX = AF_IPX -alias PF_APPLETALK = AF_APPLETALK -alias PF_NETROM = AF_NETROM -alias PF_BRIDGE = AF_BRIDGE -alias PF_ATMPVC = AF_ATMPVC -alias PF_X25 = AF_X25 -alias PF_INET6 = AF_INET6 -alias PF_ROSE = AF_ROSE -alias PF_DECnet = AF_DECnet -alias PF_NETBEUI = AF_NETBEUI -alias PF_SECURITY = AF_SECURITY -alias PF_KEY = AF_KEY -alias PF_NETLINK = AF_NETLINK -alias PF_ROUTE = AF_ROUTE -alias PF_PACKET = AF_PACKET -alias PF_ASH = AF_ASH -alias PF_ECONET = AF_ECONET -alias PF_ATMSVC = AF_ATMSVC -alias PF_RDS = AF_RDS -alias PF_SNA = AF_SNA -alias PF_IRDA = AF_IRDA -alias PF_PPPOX = AF_PPPOX -alias PF_WANPIPE = AF_WANPIPE -alias PF_LLC = AF_LLC -alias PF_CAN = AF_CAN -alias PF_TIPC = AF_TIPC -alias PF_BLUETOOTH = AF_BLUETOOTH -alias PF_IUCV = AF_IUCV -alias PF_RXRPC = AF_RXRPC -alias PF_ISDN = AF_ISDN -alias PF_PHONET = AF_PHONET -alias PF_IEEE802154 = AF_IEEE802154 -alias PF_CAIF = AF_CAIF -alias PF_ALG = AF_ALG -alias PF_NFC = AF_NFC -alias PF_VSOCK = AF_VSOCK -alias PF_KCM = AF_KCM -alias PF_QIPCRTR = AF_QIPCRTR -alias PF_MAX = AF_MAX - -# Socket Type constants -alias SOCK_STREAM = 1 -alias SOCK_DGRAM = 2 -alias SOCK_RAW = 3 -alias SOCK_RDM = 4 -alias SOCK_SEQPACKET = 5 -alias SOCK_DCCP = 6 -alias SOCK_PACKET = 10 -alias SOCK_CLOEXEC = O_CLOEXEC -alias SOCK_NONBLOCK = O_NONBLOCK - -# Address Information -alias AI_PASSIVE = 1 -alias AI_CANONNAME = 2 -alias AI_NUMERICHOST = 4 -alias AI_V4MAPPED = 8 -alias AI_ALL = 16 -alias AI_ADDRCONFIG = 32 -alias AI_IDN = 64 - -alias INET_ADDRSTRLEN = 16 -alias INET6_ADDRSTRLEN = 46 - -alias SHUT_RD = 0 -alias SHUT_WR = 1 -alias SHUT_RDWR = 2 - -alias SOL_SOCKET = 1 - -alias SO_DEBUG = 1 -alias SO_REUSEADDR = 2 -alias SO_TYPE = 3 -alias SO_ERROR = 4 -alias SO_DONTROUTE = 5 -alias SO_BROADCAST = 6 -alias SO_SNDBUF = 7 -alias SO_RCVBUF = 8 -alias SO_KEEPALIVE = 9 -alias SO_OOBINLINE = 10 -alias SO_NO_CHECK = 11 -alias SO_PRIORITY = 12 -alias SO_LINGER = 13 -alias SO_BSDCOMPAT = 14 -alias SO_REUSEPORT = 15 -alias SO_PASSCRED = 16 -alias SO_PEERCRED = 17 -alias SO_RCVLOWAT = 18 -alias SO_SNDLOWAT = 19 -alias SO_RCVTIMEO = 20 -alias SO_SNDTIMEO = 21 -alias SO_RCVTIMEO_OLD = 20 -alias SO_SNDTIMEO_OLD = 21 -alias SO_SECURITY_AUTHENTICATION = 22 -alias SO_SECURITY_ENCRYPTION_TRANSPORT = 23 -alias SO_SECURITY_ENCRYPTION_NETWORK = 24 -alias SO_BINDTODEVICE = 25 -alias SO_ATTACH_FILTER = 26 -alias SO_DETACH_FILTER = 27 -alias SO_GET_FILTER = SO_ATTACH_FILTER -alias SO_PEERNAME = 28 -alias SO_TIMESTAMP = 29 -alias SO_TIMESTAMP_OLD = 29 -alias SO_ACCEPTCONN = 30 -alias SO_PEERSEC = 31 -alias SO_SNDBUFFORCE = 32 -alias SO_RCVBUFFORCE = 33 -alias SO_PASSSEC = 34 -alias SO_TIMESTAMPNS = 35 -alias SO_TIMESTAMPNS_OLD = 35 -alias SO_MARK = 36 -alias SO_TIMESTAMPING = 37 -alias SO_TIMESTAMPING_OLD = 37 -alias SO_PROTOCOL = 38 -alias SO_DOMAIN = 39 -alias SO_RXQ_OVFL = 40 -alias SO_WIFI_STATUS = 41 -alias SCM_WIFI_STATUS = SO_WIFI_STATUS -alias SO_PEEK_OFF = 42 -alias SO_NOFCS = 43 -alias SO_LOCK_FILTER = 44 -alias SO_SELECT_ERR_QUEUE = 45 -alias SO_BUSY_POLL = 46 -alias SO_MAX_PACING_RATE = 47 -alias SO_BPF_EXTENSIONS = 48 -alias SO_INCOMING_CPU = 49 -alias SO_ATTACH_BPF = 50 -alias SO_DETACH_BPF = SO_DETACH_FILTER -alias SO_ATTACH_REUSEPORT_CBPF = 51 -alias SO_ATTACH_REUSEPORT_EBPF = 52 -alias SO_CNX_ADVICE = 53 -alias SCM_TIMESTAMPING_OPT_STATS = 54 -alias SO_MEMINFO = 55 -alias SO_INCOMING_NAPI_ID = 56 -alias SO_COOKIE = 57 -alias SCM_TIMESTAMPING_PKTINFO = 58 -alias SO_PEERGROUPS = 59 -alias SO_ZEROCOPY = 60 -alias SO_TXTIME = 61 -alias SCM_TXTIME = SO_TXTIME -alias SO_BINDTOIFINDEX = 62 -alias SO_TIMESTAMP_NEW = 63 -alias SO_TIMESTAMPNS_NEW = 64 -alias SO_TIMESTAMPING_NEW = 65 -alias SO_RCVTIMEO_NEW = 66 -alias SO_SNDTIMEO_NEW = 67 -alias SO_DETACH_REUSEPORT_BPF = 68 - - -# --- ( Network Related Structs )----------------------------------------------- -@value -@register_passable("trivial") -struct in_addr: - var s_addr: in_addr_t - - -@value -@register_passable("trivial") -struct in6_addr: - var s6_addr: StaticTuple[c_char, 16] - - -@value -@register_passable("trivial") -struct sockaddr: - var sa_family: sa_family_t - var sa_data: StaticTuple[c_char, 14] - - -@value -@register_passable("trivial") -struct sockaddr_in: - var sin_family: sa_family_t - var sin_port: in_port_t - var sin_addr: in_addr - var sin_zero: StaticTuple[c_char, 8] - - -@value -@register_passable("trivial") -struct sockaddr_in6: - var sin6_family: sa_family_t - var sin6_port: in_port_t - var sin6_flowinfo: c_uint - var sin6_addr: in6_addr - var sin6_scope_id: c_uint - - -@value -@register_passable("trivial") -struct addrinfo: - var ai_flags: c_int - var ai_family: c_int - var ai_socktype: c_int - var ai_protocol: c_int - var ai_addrlen: socklen_t - var ai_addr: UnsafePointer[sockaddr] - var ai_canonname: UnsafePointer[c_char] - var ai_next: UnsafePointer[c_void] - - fn __init__(inout self) -> None: - self.ai_flags = 0 - self.ai_family = 0 - self.ai_socktype = 0 - self.ai_protocol = 0 - self.ai_addrlen = 0 - self.ai_addr = UnsafePointer[sockaddr]() - self.ai_canonname = UnsafePointer[c_char]() - self.ai_next = UnsafePointer[c_void]() - - -fn strlen(s: UnsafePointer[c_char]) -> c_size_t: - """Libc POSIX `strlen` function - Reference: https://man7.org/linux/man-pages/man3/strlen.3p.html - Fn signature: size_t strlen(const char *s). - - Args: s: A UnsafePointer to a C string. - Returns: The length of the string. - """ - return external_call["strlen", c_size_t, UnsafePointer[c_char]](s) - - -# --- ( Network Related Syscalls & Structs )------------------------------------ - - -fn htonl(hostlong: c_uint) -> c_uint: - """Libc POSIX `htonl` function - Reference: https://man7.org/linux/man-pages/man3/htonl.3p.html - Fn signature: uint32_t htonl(uint32_t hostlong). - - Args: hostlong: A 32-bit integer in host byte order. - Returns: The value provided in network byte order. - """ - return external_call["htonl", c_uint, c_uint](hostlong) - - -fn htons(hostshort: c_ushort) -> c_ushort: - """Libc POSIX `htons` function - Reference: https://man7.org/linux/man-pages/man3/htonl.3p.html - Fn signature: uint16_t htons(uint16_t hostshort). - - Args: hostshort: A 16-bit integer in host byte order. - Returns: The value provided in network byte order. - """ - return external_call["htons", c_ushort, c_ushort](hostshort) - - -fn ntohl(netlong: c_uint) -> c_uint: - """Libc POSIX `ntohl` function - Reference: https://man7.org/linux/man-pages/man3/htonl.3p.html - Fn signature: uint32_t ntohl(uint32_t netlong). - - Args: netlong: A 32-bit integer in network byte order. - Returns: The value provided in host byte order. - """ - return external_call["ntohl", c_uint, c_uint](netlong) - - -fn ntohs(netshort: c_ushort) -> c_ushort: - """Libc POSIX `ntohs` function - Reference: https://man7.org/linux/man-pages/man3/htonl.3p.html - Fn signature: uint16_t ntohs(uint16_t netshort). - - Args: netshort: A 16-bit integer in network byte order. - Returns: The value provided in host byte order. - """ - return external_call["ntohs", c_ushort, c_ushort](netshort) - - -fn inet_ntop( - af: c_int, src: UnsafePointer[c_void], dst: UnsafePointer[c_char], size: socklen_t -) -> UnsafePointer[c_char]: - """Libc POSIX `inet_ntop` function - Reference: https://man7.org/linux/man-pages/man3/inet_ntop.3p.html. - Fn signature: const char *inet_ntop(int af, const void *restrict src, char *restrict dst, socklen_t size). - - Args: - af: Address Family see AF_ aliases. - src: A UnsafePointer to a binary address. - dst: A UnsafePointer to a buffer to store the result. - size: The size of the buffer. - - Returns: - A UnsafePointer to the buffer containing the result. - """ - return external_call[ - "inet_ntop", - UnsafePointer[c_char], # FnName, RetType - c_int, - UnsafePointer[c_void], - UnsafePointer[c_char], - socklen_t, # Args - ](af, src, dst, size) - - -fn inet_pton(af: c_int, src: UnsafePointer[c_char], dst: UnsafePointer[c_void]) -> c_int: - """Libc POSIX `inet_pton` function - Reference: https://man7.org/linux/man-pages/man3/inet_ntop.3p.html - Fn signature: int inet_pton(int af, const char *restrict src, void *restrict dst). - - Args: af: Address Family see AF_ aliases. - src: A UnsafePointer to a string containing the address. - dst: A UnsafePointer to a buffer to store the result. - Returns: 1 on success, 0 if the input is not a valid address, -1 on error. - """ - return external_call[ - "inet_pton", - c_int, - c_int, - UnsafePointer[c_char], - UnsafePointer[c_void], - ](af, src, dst) - - -fn inet_addr(cp: UnsafePointer[c_char]) -> in_addr_t: - """Libc POSIX `inet_addr` function - Reference: https://man7.org/linux/man-pages/man3/inet_addr.3p.html - Fn signature: in_addr_t inet_addr(const char *cp). - - Args: cp: A UnsafePointer to a string containing the address. - Returns: The address in network byte order. - """ - return external_call["inet_addr", in_addr_t, UnsafePointer[c_char]](cp) - - -fn inet_ntoa(addr: in_addr) -> UnsafePointer[c_char]: - """Libc POSIX `inet_ntoa` function - Reference: https://man7.org/linux/man-pages/man3/inet_addr.3p.html - Fn signature: char *inet_ntoa(struct in_addr in). - - Args: in: A UnsafePointer to a string containing the address. - Returns: The address in network byte order. - """ - return external_call["inet_ntoa", UnsafePointer[c_char], in_addr](addr) - - -fn socket(domain: c_int, type: c_int, protocol: c_int) -> c_int: - """Libc POSIX `socket` function - Reference: https://man7.org/linux/man-pages/man3/socket.3p.html - Fn signature: int socket(int domain, int type, int protocol). - - Args: domain: Address Family see AF_ aliases. - type: Socket Type see SOCK_ aliases. - protocol: The protocol to use. - Returns: A File Descriptor or -1 in case of failure. - """ - return external_call[ - "socket", c_int, c_int, c_int, c_int # FnName, RetType # Args - ](domain, type, protocol) - - -fn setsockopt( - socket: c_int, - level: c_int, - option_name: c_int, - option_value: UnsafePointer[c_void], - option_len: socklen_t, -) -> c_int: - """Libc POSIX `setsockopt` function - Reference: https://man7.org/linux/man-pages/man3/setsockopt.3p.html - Fn signature: int setsockopt(int socket, int level, int option_name, const void *option_value, socklen_t option_len). - - Args: socket: A File Descriptor. - level: The protocol level. - option_name: The option to set. - option_value: A UnsafePointer to the value to set. - option_len: The size of the value. - Returns: 0 on success, -1 on error. - """ - return external_call[ - "setsockopt", - c_int, # FnName, RetType - c_int, - c_int, - c_int, - UnsafePointer[c_void], - socklen_t, # Args - ](socket, level, option_name, option_value, option_len) - - -fn getsockname( - socket: c_int, address: UnsafePointer[sockaddr], address_len: UnsafePointer[socklen_t] -) -> c_int: - """Libc POSIX `getsockname` function - Reference: https://man7.org/linux/man-pages/man3/getsockname.3p.html - Fn signature: int getsockname(int socket, struct sockaddr *restrict address, socklen_t *restrict address_len). - - Args: socket: A File Descriptor. - address: A UnsafePointer to a buffer to store the address of the peer. - address_len: A UnsafePointer to the size of the buffer. - Returns: 0 on success, -1 on error. - """ - return external_call[ - "getsockname", - c_int, # FnName, RetType - c_int, - UnsafePointer[sockaddr], - UnsafePointer[socklen_t], # Args - ](socket, address, address_len) - - -fn getpeername( - sockfd: c_int, addr: UnsafePointer[sockaddr], address_len: UnsafePointer[socklen_t] -) -> c_int: - """Libc POSIX `getpeername` function - Reference: https://man7.org/linux/man-pages/man2/getpeername.2.html - Fn signature: int getpeername(int socket, struct sockaddr *restrict addr, socklen_t *restrict address_len). - - Args: sockfd: A File Descriptor. - addr: A UnsafePointer to a buffer to store the address of the peer. - address_len: A UnsafePointer to the size of the buffer. - Returns: 0 on success, -1 on error. - """ - return external_call[ - "getpeername", - c_int, # FnName, RetType - c_int, - UnsafePointer[sockaddr], - UnsafePointer[socklen_t], # Args - ](sockfd, addr, address_len) - - -fn bind(socket: c_int, address: UnsafePointer[sockaddr], address_len: socklen_t) -> c_int: - """Libc POSIX `bind` function - Reference: https://man7.org/linux/man-pages/man3/bind.3p.html - Fn signature: int bind(int socket, const struct sockaddr *address, socklen_t address_len). - """ - return external_call[ - "bind", c_int, c_int, UnsafePointer[sockaddr], socklen_t - ](socket, address, address_len) - - -fn listen(socket: c_int, backlog: c_int) -> c_int: - """Libc POSIX `listen` function - Reference: https://man7.org/linux/man-pages/man3/listen.3p.html - Fn signature: int listen(int socket, int backlog). - - Args: socket: A File Descriptor. - backlog: The maximum length of the queue of pending connections. - Returns: 0 on success, -1 on error. - """ - return external_call["listen", c_int, c_int, c_int](socket, backlog) - - -fn accept( - socket: c_int, address: UnsafePointer[sockaddr], address_len: UnsafePointer[socklen_t] -) -> c_int: - """Libc POSIX `accept` function - Reference: https://man7.org/linux/man-pages/man3/accept.3p.html - Fn signature: int accept(int socket, struct sockaddr *restrict address, socklen_t *restrict address_len). - - Args: socket: A File Descriptor. - address: A UnsafePointer to a buffer to store the address of the peer. - address_len: A UnsafePointer to the size of the buffer. - Returns: A File Descriptor or -1 in case of failure. - """ - return external_call[ - "accept", - c_int, # FnName, RetType - c_int, - UnsafePointer[sockaddr], - UnsafePointer[socklen_t], # Args - ](socket, address, address_len) - - -fn connect(socket: c_int, address: UnsafePointer[sockaddr], address_len: socklen_t) -> c_int: - """Libc POSIX `connect` function - Reference: https://man7.org/linux/man-pages/man3/connect.3p.html - Fn signature: int connect(int socket, const struct sockaddr *address, socklen_t address_len). - - Args: socket: A File Descriptor. - address: A UnsafePointer to the address to connect to. - address_len: The size of the address. - Returns: 0 on success, -1 on error. - """ - return external_call[ - "connect", c_int, c_int, UnsafePointer[sockaddr], socklen_t # FnName, RetType # Args - ](socket, address, address_len) - - -# fn recv( -# socket: c_int, buffer: UnsafePointer[c_void], length: c_size_t, flags: c_int -# ) -> c_ssize_t: -# """Libc POSIX `recv` function -# Reference: https://man7.org/linux/man-pages/man3/recv.3p.html -# Fn signature: ssize_t recv(int socket, void *buffer, size_t length, int flags). -# """ -# return external_call[ -# "recv", -# c_ssize_t, # FnName, RetType -# c_int, -# UnsafePointer[c_void], -# c_size_t, -# c_int, # Args -# ](socket, buffer, length, flags) - - -fn recv( - socket: c_int, - buffer: UnsafePointer[UInt8], - length: c_size_t, - flags: c_int, -) -> c_ssize_t: - """Libc POSIX `recv` function - Reference: https://man7.org/linux/man-pages/man3/recv.3p.html - Fn signature: ssize_t recv(int socket, void *buffer, size_t length, int flags). - """ - return external_call[ - "recv", - c_ssize_t, # FnName, RetType - c_int, - UnsafePointer[UInt8], - c_size_t, - c_int, # Args - ](socket, buffer, length, flags) - -fn send( - socket: c_int, buffer: UnsafePointer[c_void], length: c_size_t, flags: c_int -) -> c_ssize_t: - """Libc POSIX `send` function - Reference: https://man7.org/linux/man-pages/man3/send.3p.html - Fn signature: ssize_t send(int socket, const void *buffer, size_t length, int flags). - - Args: socket: A File Descriptor. - buffer: A UnsafePointer to the buffer to send. - length: The size of the buffer. - flags: Flags to control the behaviour of the function. - Returns: The number of bytes sent or -1 in case of failure. - """ - return external_call[ - "send", - c_ssize_t, # FnName, RetType - c_int, - UnsafePointer[c_void], - c_size_t, - c_int, # Args - ](socket, buffer, length, flags) - - -fn shutdown(socket: c_int, how: c_int) -> c_int: - """Libc POSIX `shutdown` function - Reference: https://man7.org/linux/man-pages/man3/shutdown.3p.html - Fn signature: int shutdown(int socket, int how). - - Args: socket: A File Descriptor. - how: How to shutdown the socket. - Returns: 0 on success, -1 on error. - """ - return external_call["shutdown", c_int, c_int, c_int]( # FnName, RetType # Args - socket, how - ) - - -fn getaddrinfo( - nodename: UnsafePointer[c_char], - servname: UnsafePointer[c_char], - hints: UnsafePointer[addrinfo], - res: UnsafePointer[UnsafePointer[addrinfo]], -) -> c_int: - """Libc POSIX `getaddrinfo` function - Reference: https://man7.org/linux/man-pages/man3/getaddrinfo.3p.html - Fn signature: int getaddrinfo(const char *restrict nodename, const char *restrict servname, const struct addrinfo *restrict hints, struct addrinfo **restrict res). - """ - return external_call[ - "getaddrinfo", - c_int, # FnName, RetType - UnsafePointer[c_char], - UnsafePointer[c_char], - UnsafePointer[addrinfo], # Args - UnsafePointer[UnsafePointer[addrinfo]], # Args - ](nodename, servname, hints, res) - - -fn gai_strerror(ecode: c_int) -> UnsafePointer[c_char]: - """Libc POSIX `gai_strerror` function - Reference: https://man7.org/linux/man-pages/man3/gai_strerror.3p.html - Fn signature: const char *gai_strerror(int ecode). - - Args: ecode: The error code. - Returns: A UnsafePointer to a string describing the error. - """ - return external_call[ - "gai_strerror", UnsafePointer[c_char], c_int # FnName, RetType # Args - ](ecode) - - -fn inet_pton(address_family: Int, address: String) -> Int: - var ip_buf_size = 4 - if address_family == AF_INET6: - ip_buf_size = 16 - - var ip_buf = UnsafePointer[c_void].alloc(ip_buf_size) - var conv_status = inet_pton( - rebind[c_int](address_family), to_char_ptr(address), ip_buf - ) - return int(ip_buf.bitcast[c_uint]()) - - -# --- ( File Related Syscalls & Structs )--------------------------------------- -alias O_NONBLOCK = 16384 -alias O_ACCMODE = 3 -alias O_CLOEXEC = 524288 - - -fn close(fildes: c_int) -> c_int: - """Libc POSIX `close` function - Reference: https://man7.org/linux/man-pages/man3/close.3p.html - Fn signature: int close(int fildes). - - Args: - fildes: A File Descriptor to close. - - Returns: - Upon successful completion, 0 shall be returned; otherwise, -1 - shall be returned and errno set to indicate the error. - """ - return external_call["close", c_int, c_int](fildes) - - -fn open[*T: AnyType](path: UnsafePointer[c_char], oflag: c_int, *args: *T) -> c_int: - """Libc POSIX `open` function - Reference: https://man7.org/linux/man-pages/man3/open.3p.html - Fn signature: int open(const char *path, int oflag, ...). - - Args: - path: A UnsafePointer to a C string containing the path to open. - oflag: The flags to open the file with. - args: The optional arguments. - Returns: - A File Descriptor or -1 in case of failure - """ - return external_call["open", c_int](path, oflag, args) - - -fn printf[*T: AnyType](format: UnsafePointer[c_char], *args: *T) -> c_int: - """Libc POSIX `printf` function - Reference: https://man7.org/linux/man-pages/man3/fprintf.3p.html - Fn signature: int printf(const char *restrict format, ...). - - Args: format: A UnsafePointer to a C string containing the format. - args: The optional arguments. - Returns: The number of bytes written or -1 in case of failure. - """ - return external_call[ - "printf", - c_int, # FnName, RetType - ](format, args) - - - -fn read(fildes: c_int, buf: UnsafePointer[c_void], nbyte: c_size_t) -> c_int: - """Libc POSIX `read` function - Reference: https://man7.org/linux/man-pages/man3/read.3p.html - Fn signature: sssize_t read(int fildes, void *buf, size_t nbyte). - - Args: fildes: A File Descriptor. - buf: A UnsafePointer to a buffer to store the read data. - nbyte: The number of bytes to read. - Returns: The number of bytes read or -1 in case of failure. - """ - return external_call["read", c_ssize_t, c_int, UnsafePointer[c_void], c_size_t]( - fildes, buf, nbyte - ) - - -fn write(fildes: c_int, buf: UnsafePointer[c_void], nbyte: c_size_t) -> c_int: - """Libc POSIX `write` function - Reference: https://man7.org/linux/man-pages/man3/write.3p.html - Fn signature: ssize_t write(int fildes, const void *buf, size_t nbyte). - - Args: fildes: A File Descriptor. - buf: A UnsafePointer to a buffer to write. - nbyte: The number of bytes to write. - Returns: The number of bytes written or -1 in case of failure. - """ - return external_call["write", c_ssize_t, c_int, UnsafePointer[c_void], c_size_t]( - fildes, buf, nbyte - ) - - -# --- ( Testing Functions ) ---------------------------------------------------- - - -fn __test_getaddrinfo__(): - var ip_addr = "127.0.0.1" - var port = 8083 - - var servinfo = UnsafePointer[addrinfo]().alloc(1) - servinfo[0] = addrinfo() - - var hints = addrinfo() - hints.ai_family = AF_INET - hints.ai_socktype = SOCK_STREAM - hints.ai_flags = AI_PASSIVE - # var hints_ptr = - - var status = getaddrinfo( - to_char_ptr(ip_addr), - UnsafePointer[UInt8](), - UnsafePointer.address_of(hints), - UnsafePointer.address_of(servinfo), - ) - var msg_ptr = gai_strerror(c_int(status)) - _ = external_call["printf", c_int, UnsafePointer[c_char], UnsafePointer[c_char]]( - to_char_ptr("gai_strerror: %s"), msg_ptr - ) - var msg = c_charptr_to_string(msg_ptr) - print("getaddrinfo satus: " + msg) - - -# fn __test_socket_client__(): -# var ip_addr = "127.0.0.1" # The server's hostname or IP address -# var port = 8080 # The port used by the server -# var address_family = AF_INET - -# var ip_buf = UnsafePointer[c_void].alloc(4) -# var conv_status = inet_pton(address_family, to_char_ptr(ip_addr), ip_buf) -# var raw_ip = ip_buf.bitcast[c_uint]() - -# print("inet_pton: " + raw_ip.__str__() + " :: status: " + conv_status.__str__()) - -# var bin_port = htons(UInt16(port)) -# print("htons: " + "\n" + bin_port.__str__()) - -# var ai = sockaddr_in(address_family, bin_port, raw_ip, StaticTuple[c_char, 8]()) -# var ai_ptr = UnsafePointer[sockaddr_in].address_of(ai).bitcast[sockaddr]() - -# var sockfd = socket(address_family, SOCK_STREAM, 0) -# if sockfd == -1: -# print("Socket creation error") -# print("sockfd: " + "\n" + sockfd.__str__()) - -# if connect(sockfd, ai_ptr, sizeof[sockaddr_in]()) == -1: -# _ = shutdown(sockfd, SHUT_RDWR) -# print("Connection error") -# return # Ensure to exit if connection fails - -# var msg = to_char_ptr("Hello, world Server") -# var bytes_sent = send(sockfd, msg, strlen(msg), 0) -# if bytes_sent == -1: -# print("Failed to send message") -# else: -# print("Message sent") -# var buf_size = 1024 -# var buf = UnsafePointer[UInt8]().alloc(buf_size) -# var bytes_recv = recv(sockfd, buf, buf_size, 0) -# if bytes_recv == -1: -# print("Failed to receive message") -# else: -# print("Received Message: ") -# print(String(buf.bitcast[UInt8](), bytes_recv)) - -# _ = shutdown(sockfd, SHUT_RDWR) -# var close_status = close(sockfd) -# if close_status == -1: -# print("Failed to close socket") - - -# fn __test_socket_server__() raises: -# var ip_addr = "127.0.0.1" -# var port = 8083 - -# var address_family = AF_INET -# var ip_buf_size = 4 -# if address_family == AF_INET6: -# ip_buf_size = 16 - -# var ip_buf = UnsafePointer[c_void].alloc(ip_buf_size) -# var conv_status = inet_pton(address_family, to_char_ptr(ip_addr), ip_buf) -# var raw_ip = ip_buf.bitcast[c_uint]() -# print("inet_pton: " + raw_ip.__str__() + " :: status: " + conv_status.__str__()) - -# var bin_port = htons(UInt16(port)) -# print("htons: " + "\n" + bin_port.__str__()) - -# var ai = sockaddr_in(address_family, bin_port, raw_ip, StaticTuple[c_char, 8]()) -# var ai_ptr = UnsafePointer[sockaddr_in].address_of(ai).bitcast[sockaddr]() - -# var sockfd = socket(address_family, SOCK_STREAM, 0) -# if sockfd == -1: -# print("Socket creation error") -# print("sockfd: " + "\n" + sockfd.__str__()) - -# var yes: Int = 1 -# if ( -# setsockopt( -# sockfd, -# SOL_SOCKET, -# SO_REUSEADDR, -# UnsafePointer[Int].address_of(yes).bitcast[c_void](), -# sizeof[Int](), -# ) -# == -1 -# ): -# print("set socket options failed") - -# if bind(sockfd, ai_ptr, sizeof[sockaddr_in]()) == -1: -# # close(sockfd) -# _ = shutdown(sockfd, SHUT_RDWR) -# print("Binding socket failed. Wait a few seconds and try again?") - -# if listen(sockfd, c_int(128)) == -1: -# print("Listen failed.\n on sockfd " + sockfd.__str__()) - -# print( -# "server: started at " -# + ip_addr -# + ":" -# + port.__str__() -# + " on sockfd " -# + sockfd.__str__() -# + "Waiting for connections..." -# ) - -# var their_addr_ptr = UnsafePointer[sockaddr].alloc(1) -# var sin_size = socklen_t(sizeof[socklen_t]()) -# var new_sockfd = accept( -# sockfd, their_addr_ptr, UnsafePointer[socklen_t].address_of(sin_size) -# ) -# if new_sockfd == -1: -# print("Accept failed") -# # close(sockfd) -# _ = shutdown(sockfd, SHUT_RDWR) - -# var msg = "Hello, Mojo!" -# if send(new_sockfd, to_char_ptr(msg).bitcast[c_void](), len(msg), 0) == -1: -# print("Failed to send response") -# print("Message sent succesfully") -# _ = shutdown(sockfd, SHUT_RDWR) - -# var close_status = close(new_sockfd) -# if close_status == -1: -# print("Failed to close new_sockfd") diff --git a/external/morrow/__init__.mojo b/external/morrow/__init__.mojo deleted file mode 100644 index 63bde0cf..00000000 --- a/external/morrow/__init__.mojo +++ /dev/null @@ -1,5 +0,0 @@ -from .morrow import Morrow -from .timezone import TimeZone -from .timedelta import TimeDelta - -alias __version__ = "0.4.0" diff --git a/external/morrow/_libc.mojo b/external/morrow/_libc.mojo deleted file mode 100644 index d57f0106..00000000 --- a/external/morrow/_libc.mojo +++ /dev/null @@ -1,93 +0,0 @@ -from memory import UnsafePointer -from sys.ffi import external_call - -alias c_void = UInt8 -alias c_char = UInt8 -alias c_schar = Int8 -alias c_uchar = UInt8 -alias c_short = Int16 -alias c_ushort = UInt16 -alias c_int = Int32 -alias c_uint = UInt32 -alias c_long = Int64 -alias c_ulong = UInt64 -alias c_float = Float32 -alias c_double = Float64 - - -@value -@register_passable("trivial") -struct CTimeval: - var tv_sec: Int # Seconds - var tv_usec: Int # Microseconds - - fn __init__(inout self, tv_sec: Int = 0, tv_usec: Int = 0): - self.tv_sec = tv_sec - self.tv_usec = tv_usec - - -@value -@register_passable("trivial") -struct CTm: - var tm_sec: Int32 # Seconds - var tm_min: Int32 # Minutes - var tm_hour: Int32 # Hour - var tm_mday: Int32 # Day of the month - var tm_mon: Int32 # Month - var tm_year: Int32 # Year minus 1900 - var tm_wday: Int32 # Day of the week - var tm_yday: Int32 # Day of the year - var tm_isdst: Int32 # Daylight savings flag - var tm_gmtoff: Int64 # localtime zone offset seconds - - fn __init__(inout self): - self.tm_sec = 0 - self.tm_min = 0 - self.tm_hour = 0 - self.tm_mday = 0 - self.tm_mon = 0 - self.tm_year = 0 - self.tm_wday = 0 - self.tm_yday = 0 - self.tm_isdst = 0 - self.tm_gmtoff = 0 - - -@always_inline -fn c_gettimeofday() -> CTimeval: - var tv = CTimeval() - var p_tv = UnsafePointer[CTimeval].address_of(tv) - external_call["gettimeofday", NoneType, UnsafePointer[CTimeval], Int32](p_tv, 0) - return tv - - -@always_inline -fn c_localtime(owned tv_sec: Int) -> CTm: - var p_tv_sec = UnsafePointer[Int].address_of(tv_sec) - var tm = external_call["localtime", UnsafePointer[CTm], UnsafePointer[Int]](p_tv_sec) - return tm[0] - - -@always_inline -fn c_strptime(time_str: String, time_format: String) -> CTm: - var tm = CTm() - var p_tm = UnsafePointer[CTm].address_of(tm) - external_call["strptime", NoneType, UnsafePointer[c_char], UnsafePointer[c_char], UnsafePointer[CTm]]( - to_char_ptr(time_str), to_char_ptr(time_format), p_tm - ) - return tm - - -@always_inline -fn c_gmtime(owned tv_sec: Int) -> CTm: - var p_tv_sec = UnsafePointer[Int].address_of(tv_sec) - var tm = external_call["gmtime", UnsafePointer[CTm], UnsafePointer[Int]](p_tv_sec) - return tm[0] - - -fn to_char_ptr(s: String) -> UnsafePointer[c_char]: - """Only ASCII-based strings.""" - var ptr = UnsafePointer[c_char]().alloc(len(s)) - for i in range(len(s)): - ptr.store(i, ord(s[i])) - return ptr diff --git a/external/morrow/_py.mojo b/external/morrow/_py.mojo deleted file mode 100644 index 1e02f8ec..00000000 --- a/external/morrow/_py.mojo +++ /dev/null @@ -1,11 +0,0 @@ -from python import Python - - -fn py_dt_datetime() raises -> PythonObject: - var _datetime = Python.import_module("datetime") - return _datetime.datetime - - -fn py_time() raises -> PythonObject: - var _time = Python.import_module("time") - return _time diff --git a/external/morrow/constants.mojo b/external/morrow/constants.mojo deleted file mode 100644 index e8b2833b..00000000 --- a/external/morrow/constants.mojo +++ /dev/null @@ -1,62 +0,0 @@ -from utils import StaticTuple - - -# todo: hardcode for tmp -alias _MAX_TIMESTAMP: Int = 32503737600 -alias MAX_TIMESTAMP = _MAX_TIMESTAMP -alias MAX_TIMESTAMP_MS = MAX_TIMESTAMP * 1000 -alias MAX_TIMESTAMP_US = MAX_TIMESTAMP * 1_000_000 - -alias _DAYS_IN_MONTH = VariadicList[Int]( - -1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 -) -alias _DAYS_BEFORE_MONTH = VariadicList[Int]( - -1, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 -) # -1 is a placeholder for indexing purposes. - - -alias MONTH_NAMES = StaticTuple[StringLiteral, 13]( - "", - "January", - "February", - "March", - "April", - "May", - "June", - "July", - "August", - "September", - "October", - "November", - "December", -) - -alias MONTH_ABBREVIATIONS = StaticTuple[StringLiteral, 13]( - "", - "Jan", - "Feb", - "Mar", - "Apr", - "May", - "Jun", - "Jul", - "Aug", - "Sep", - "Oct", - "Nov", - "Dec", -) - -alias DAY_NAMES = StaticTuple[StringLiteral, 8]( - "", - "Monday", - "Tuesday", - "Wednesday", - "Thursday", - "Friday", - "Saturday", - "Sunday", -) -alias DAY_ABBREVIATIONS = StaticTuple[StringLiteral, 8]( - "", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" -) diff --git a/external/morrow/formatter.mojo b/external/morrow/formatter.mojo deleted file mode 100644 index 4a350547..00000000 --- a/external/morrow/formatter.mojo +++ /dev/null @@ -1,185 +0,0 @@ -from collections.vector import InlinedFixedVector -from utils.static_tuple import StaticTuple -from .util import rjust -from .constants import MONTH_NAMES, MONTH_ABBREVIATIONS, DAY_NAMES, DAY_ABBREVIATIONS -from .timezone import UTC_TZ - -alias formatter = _Formatter() - - -struct _Formatter: - var _sub_chrs: InlinedFixedVector[Int, 128] - - fn __init__(inout self): - self._sub_chrs = InlinedFixedVector[Int, 128](0) - for i in range(128): - self._sub_chrs[i] = 0 - self._sub_chrs[_Y] = 4 - self._sub_chrs[_M] = 4 - self._sub_chrs[_D] = 2 - self._sub_chrs[_d] = 4 - self._sub_chrs[_H] = 2 - self._sub_chrs[_h] = 2 - self._sub_chrs[_m] = 2 - self._sub_chrs[_s] = 2 - self._sub_chrs[_S] = 6 - self._sub_chrs[_Z] = 3 - self._sub_chrs[_A] = 1 - self._sub_chrs[_a] = 1 - - fn format(self, m: Morrow, fmt: String) raises -> String: - """ - "YYYY[abc]MM" -> repalce("YYYY") + "abc" + replace("MM") - """ - if len(fmt) == 0: - return "" - var ret: String = "" - var in_bracket = False - var start_idx = 0 - for i in range(len(fmt)): - if fmt[i] == "[": - if in_bracket: - ret += "[" - else: - in_bracket = True - ret += self.replace(m, fmt[start_idx:i]) - start_idx = i + 1 - elif fmt[i] == "]": - if in_bracket: - ret += fmt[start_idx:i] - in_bracket = False - else: - ret += self.replace(m, fmt[start_idx:i]) - ret += "]" - start_idx = i + 1 - if in_bracket: - ret += "[" - if start_idx < len(fmt): - ret += self.replace(m, fmt[start_idx:]) - return ret - - fn replace(self, m: Morrow, s: String) raises -> String: - """ - split token and replace - """ - if len(s) == 0: - return "" - var ret: String = "" - var match_chr_ord = 0 - var match_count = 0 - for i in range(len(s)): - var c = ord(s[i]) - if 0 < c < 128 and self._sub_chrs[c] > 0: - if c == match_chr_ord: - match_count += 1 - else: - ret += self.replace_token(m, match_chr_ord, match_count) - match_chr_ord = c - match_count = 1 - if match_count == self._sub_chrs[c]: - ret += self.replace_token(m, match_chr_ord, match_count) - match_chr_ord = 0 - else: - if match_chr_ord > 0: - ret += self.replace_token(m, match_chr_ord, match_count) - match_chr_ord = 0 - ret += s[i] - if match_chr_ord > 0: - ret += self.replace_token(m, match_chr_ord, match_count) - return ret - - fn replace_token(self, m: Morrow, token: Int, token_count: Int) raises -> String: - if token == _Y: - if token_count == 1: - return "Y" - if token_count == 2: - return rjust(m.year, 4, "0")[2:4] - if token_count == 4: - return rjust(m.year, 4, "0") - elif token == _M: - if token_count == 1: - return String(m.month) - if token_count == 2: - return rjust(m.month, 2, "0") - if token_count == 3: - return String(MONTH_ABBREVIATIONS[m.month]) - if token_count == 4: - return String(MONTH_NAMES[m.month]) - elif token == _D: - if token_count == 1: - return String(m.day) - if token_count == 2: - return rjust(m.day, 2, "0") - elif token == _H: - if token_count == 1: - return String(m.hour) - if token_count == 2: - return rjust(m.hour, 2, "0") - elif token == _h: - var h_12 = m.hour - if m.hour > 12: - h_12 -= 12 - if token_count == 1: - return String(h_12) - if token_count == 2: - return rjust(h_12, 2, "0") - elif token == _m: - if token_count == 1: - return String(m.minute) - if token_count == 2: - return rjust(m.minute, 2, "0") - elif token == _s: - if token_count == 1: - return String(m.second) - if token_count == 2: - return rjust(m.second, 2, "0") - elif token == _S: - if token_count == 1: - return String(m.microsecond // 100000) - if token_count == 2: - return rjust(m.microsecond // 10000, 2, "0") - if token_count == 3: - return rjust(m.microsecond // 1000, 3, "0") - if token_count == 4: - return rjust(m.microsecond // 100, 4, "0") - if token_count == 5: - return rjust(m.microsecond // 10, 5, "0") - if token_count == 6: - return rjust(m.microsecond, 6, "0") - elif token == _d: - if token_count == 1: - return String(m.isoweekday()) - if token_count == 3: - return String(DAY_ABBREVIATIONS[m.isoweekday()]) - if token_count == 4: - return String(DAY_NAMES[m.isoweekday()]) - elif token == _Z: - if token_count == 3: - return UTC_TZ.name if m.tz.is_none() else m.tz.name - var separator = "" if token_count == 1 else ":" - if m.tz.is_none(): - return UTC_TZ.format(separator) - else: - return m.tz.format(separator) - - elif token == _a: - return "am" if m.hour < 12 else "pm" - elif token == _A: - return "AM" if m.hour < 12 else "PM" - return "" - - -alias _Y = ord("Y") -alias _M = ord("M") -alias _D = ord("D") -alias _d = ord("d") -alias _H = ord("H") -alias _h = ord("h") -alias _m = ord("m") -alias _s = ord("s") -alias _S = ord("S") -alias _X = ord("X") -alias _x = ord("x") -alias _Z = ord("Z") -alias _A = ord("A") -alias _a = ord("a") diff --git a/external/morrow/morrow.mojo b/external/morrow/morrow.mojo deleted file mode 100644 index cda506ab..00000000 --- a/external/morrow/morrow.mojo +++ /dev/null @@ -1,353 +0,0 @@ -from ._py import py_dt_datetime -from .util import normalize_timestamp, rjust, _ymd2ord, _days_before_year -from ._libc import c_gettimeofday, c_localtime, c_gmtime, c_strptime -from ._libc import CTimeval, CTm -from .timezone import TimeZone -from .timedelta import TimeDelta -from .formatter import formatter -from .constants import _DAYS_BEFORE_MONTH, _DAYS_IN_MONTH -from python.object import PythonObject -from python import Python - - -alias _DI400Y = 146097 # number of days in 400 years -alias _DI100Y = 36524 # " " " " 100 " -alias _DI4Y = 1461 # " " " " 4 " - - -@value -struct Morrow(StringableRaising): - var year: Int - var month: Int - var day: Int - var hour: Int - var minute: Int - var second: Int - var microsecond: Int - var tz: TimeZone - - fn __init__( - inout self, - year: Int, - month: Int, - day: Int, - hour: Int = 0, - minute: Int = 0, - second: Int = 0, - microsecond: Int = 0, - tz: TimeZone = TimeZone.none(), - ) raises: - self.year = year - self.month = month - self.day = day - self.hour = hour - self.minute = minute - self.second = second - self.microsecond = microsecond - self.tz = tz - - @staticmethod - fn now() raises -> Self: - var t = c_gettimeofday() - return Self._fromtimestamp(t, False) - - @staticmethod - fn utcnow() raises -> Self: - var t = c_gettimeofday() - return Self._fromtimestamp(t, True) - - @staticmethod - fn _fromtimestamp(t: CTimeval, utc: Bool) raises -> Self: - var tm: CTm - var tz: TimeZone - if utc: - tm = c_gmtime(t.tv_sec) - tz = TimeZone(0, "UTC") - else: - tm = c_localtime(t.tv_sec) - tz = TimeZone(int(tm.tm_gmtoff), "local") - - var result = Self( - int(tm.tm_year) + 1900, - int(tm.tm_mon) + 1, - int(tm.tm_mday), - int(tm.tm_hour), - int(tm.tm_min), - int(tm.tm_sec), - t.tv_usec, - tz, - ) - return result - - @staticmethod - fn fromtimestamp(timestamp: Float64) raises -> Self: - var timestamp_ = normalize_timestamp(timestamp) - var t = CTimeval(int(timestamp_)) - return Self._fromtimestamp(t, False) - - @staticmethod - fn utcfromtimestamp(timestamp: Float64) raises -> Self: - var timestamp_ = normalize_timestamp(timestamp) - var t = CTimeval(int(timestamp_)) - return Self._fromtimestamp(t, True) - - @staticmethod - fn strptime( - date_str: String, fmt: String, tzinfo: TimeZone = TimeZone.none() - ) raises -> Self: - """ - Create a Morrow instance from a date string and format, - in the style of ``datetime.strptime``. Optionally replaces the parsed TimeZone. - - Usage:: - - >>> Morrow.strptime('20-01-2019 15:49:10', '%d-%m-%Y %H:%M:%S') - - """ - var tm = c_strptime(date_str, fmt) - var tz = TimeZone(int(tm.tm_gmtoff)) if tzinfo.is_none() else tzinfo - return Self( - int(tm.tm_year) + 1900, - int(tm.tm_mon) + 1, - int(tm.tm_mday), - int(tm.tm_hour), - int(tm.tm_min), - int(tm.tm_sec), - 0, - tz, - ) - - @staticmethod - fn strptime(date_str: String, fmt: String, tz_str: String) raises -> Self: - """ - Create a Morrow instance by time_zone_string with utc format. - - Usage:: - - >>> Morrow.strptime('20-01-2019 15:49:10', '%d-%m-%Y %H:%M:%S', '+08:00') - - """ - var tzinfo = TimeZone.from_utc(tz_str) - return Self.strptime(date_str, fmt, tzinfo) - - fn format(self, fmt: String = "YYYY-MM-DD HH:mm:ss ZZ") raises -> String: - """Returns a string representation of the `Morrow` - formatted according to the provided format string. - - :param fmt: the format string. - - Usage:: - >>> var m = Morrow.now() - >>> m.format('YYYY-MM-DD HH:mm:ss ZZ') - '2013-05-09 03:56:47 -00:00' - - >>> m.format('MMMM DD, YYYY') - 'May 09, 2013' - - >>> m.format() - '2013-05-09 03:56:47 -00:00' - - """ - return formatter.format(self, fmt) - - fn isoformat( - self, sep: String = "T", timespec: StringLiteral = "auto" - ) raises -> String: - """Return the time formatted according to ISO. - - The full format looks like 'YYYY-MM-DD HH:MM:SS.mmmmmm'. - - If self.tzinfo is not None, the UTC offset is also attached, giving - giving a full format of 'YYYY-MM-DD HH:MM:SS.mmmmmm+HH:MM'. - - Optional argument sep specifies the separator between date and - time, default 'T'. - - The optional argument timespec specifies the number of additional - terms of the time to include. Valid options are 'auto', 'hours', - 'minutes', 'seconds', 'milliseconds' and 'microseconds'. - """ - var date_str = ( - rjust(self.year, 4, "0") - + "-" - + rjust(self.month, 2, "0") - + "-" - + rjust(self.day, 2, "0") - ) - var time_str = String("") - if timespec == "auto" or timespec == "microseconds": - time_str = ( - rjust(self.hour, 2, "0") - + ":" - + rjust(self.minute, 2, "0") - + ":" - + rjust(self.second, 2, "0") - + "." - + rjust(self.microsecond, 6, "0") - ) - elif timespec == "milliseconds": - time_str = ( - rjust(self.hour, 2, "0") - + ":" - + rjust(self.minute, 2, "0") - + ":" - + rjust(self.second, 2, "0") - + "." - + rjust(self.microsecond // 1000, 3, "0") - ) - elif timespec == "seconds": - time_str = ( - rjust(self.hour, 2, "0") - + ":" - + rjust(self.minute, 2, "0") - + ":" - + rjust(self.second, 2, "0") - ) - elif timespec == "minutes": - time_str = rjust(self.hour, 2, "0") + ":" + rjust(self.minute, 2, "0") - elif timespec == "hours": - time_str = rjust(self.hour, 2, "0") - else: - raise Error() - if self.tz.is_none(): - return sep.join(date_str, time_str) - else: - return sep.join(date_str, time_str) + self.tz.format() - - fn toordinal(self) raises -> Int: - """Return proleptic Gregorian ordinal for the year, month and day. - - January 1 of year 1 is day 1. Only the year, month and day values - contribute to the result. - """ - return _ymd2ord(self.year, self.month, self.day) - - @staticmethod - fn fromordinal(ordinal: Int) raises -> Self: - """Construct a Morrow from a proleptic Gregorian ordinal. - - January 1 of year 1 is day 1. Only the year, month and day are - non-zero in the result. - """ - # n is a 1-based index, starting at 1-Jan-1. The pattern of leap years - # repeats exactly every 400 years. The basic strategy is to find the - # closest 400-year boundary at or before n, then work with the offset - # from that boundary to n. Life is much clearer if we subtract 1 from - # n first -- then the values of n at 400-year boundaries are exactly - # those divisible by _DI400Y: - # - # D M Y n n-1 - # -- --- ---- ---------- ---------------- - # 31 Dec -400 -_DI400Y -_DI400Y -1 - # 1 Jan -399 -_DI400Y +1 -_DI400Y 400-year boundary - # ... - # 30 Dec 000 -1 -2 - # 31 Dec 000 0 -1 - # 1 Jan 001 1 0 400-year boundary - # 2 Jan 001 2 1 - # 3 Jan 001 3 2 - # ... - # 31 Dec 400 _DI400Y _DI400Y -1 - # 1 Jan 401 _DI400Y +1 _DI400Y 400-year boundary - var n = ordinal - n -= 1 - var n400 = n // _DI400Y - n = n % _DI400Y - var year = n400 * 400 + 1 # ..., -399, 1, 401, ... - - # Now n is the (non-negative) offset, in days, from January 1 of year, to - # the desired date. Now compute how many 100-year cycles precede n. - # Note that it's possible for n100 to equal 4! In that case 4 full - # 100-year cycles precede the desired day, which implies the desired - # day is December 31 at the end of a 400-year cycle. - var n100 = n // _DI100Y - n = n % _DI100Y - - # Now compute how many 4-year cycles precede it. - var n4 = n // _DI4Y - n = n % _DI4Y - - # And now how many single years. Again n1 can be 4, and again meaning - # that the desired day is December 31 at the end of the 4-year cycle. - var n1 = n // 365 - n = n % 365 - - year += n100 * 100 + n4 * 4 + n1 - if n1 == 4 or n100 == 4: - return Self(year - 1, 12, 31) - - # Now the year is correct, and n is the offset from January 1. We find - # the month via an estimate that's either exact or one too large. - var leapyear = n1 == 3 and (n4 != 24 or n100 == 3) - var month = (n + 50) >> 5 - var preceding: Int - if month > 2 and leapyear: - preceding = _DAYS_BEFORE_MONTH[month] + 1 - else: - preceding = _DAYS_BEFORE_MONTH[month] - if preceding > n: # estimate is too large - month -= 1 - if month == 2 and leapyear: - preceding -= _DAYS_BEFORE_MONTH[month] + 1 - else: - preceding -= _DAYS_BEFORE_MONTH[month] - n -= preceding - - # Now the year and month are correct, and n is the offset from the - # start of that month: we're done! - return Self(year, month, n + 1) - - fn isoweekday(self) raises -> Int: - # "Return day of the week, where Monday == 1 ... Sunday == 7." - # 1-Jan-0001 is a Monday - return self.toordinal() % 7 or 7 - - fn __str__(self) raises -> String: - return self.isoformat() - - fn __sub__(self, other: Self) raises -> TimeDelta: - var days1 = self.toordinal() - var days2 = other.toordinal() - var secs1 = self.second + self.minute * 60 + self.hour * 3600 - var secs2 = other.second + other.minute * 60 + other.hour * 3600 - var base = TimeDelta( - days1 - days2, secs1 - secs2, self.microsecond - other.microsecond - ) - return base - - fn to_py(self) raises -> PythonObject: - # todo: add tz later - var dateimte = Python.import_module("datetime") - return dateimte.datetime( - self.year, - self.month, - self.day, - self.hour, - self.minute, - self.second, - self.microsecond, - ) - - @staticmethod - fn from_py(py_datetime: PythonObject) raises -> Morrow: - # Python.is_type not working, use __class__.__name__ instead - if py_datetime.__class__.__name__ == "datetime": - return Morrow( - int(py_datetime.year), - int(py_datetime.month), - int(py_datetime.day), - int(py_datetime.hour), - int(py_datetime.minute), - int(py_datetime.second), - int(py_datetime.second), - ) - elif py_datetime.__class__.__name__ == "date": - return Morrow( - int(py_datetime.year), - int(py_datetime.month), - int(py_datetime.day), - ) - else: - raise Error( - "invalid python object, only support py builtin datetime or date" - ) diff --git a/external/morrow/timedelta.mojo b/external/morrow/timedelta.mojo deleted file mode 100644 index ddd41b17..00000000 --- a/external/morrow/timedelta.mojo +++ /dev/null @@ -1,181 +0,0 @@ -from .util import rjust - -alias SECONDS_OF_DAY = 24 * 3600 - - -struct TimeDelta(Stringable): - var days: Int - var seconds: Int - var microseconds: Int - - fn __init__( - inout self, - days: Int = 0, - seconds: Int = 0, - microseconds: Int = 0, - milliseconds: Int = 0, - minutes: Int = 0, - hours: Int = 0, - weeks: Int = 0, - ): - self.days = 0 - self.seconds = 0 - self.microseconds = 0 - - var days_ = days - var seconds_ = seconds - var microseconds_ = microseconds - - # Normalize everything to days, seconds, microseconds. - days_ += weeks * 7 - seconds_ += minutes * 60 + hours * 3600 - microseconds_ += milliseconds * 1000 - - self.days = days_ - days_ = seconds_ // SECONDS_OF_DAY - seconds_ = seconds_ % SECONDS_OF_DAY - self.days += days_ - self.seconds += seconds_ - - seconds_ = microseconds_ // 1000000 - microseconds_ = microseconds_ % 1000000 - days_ = seconds_ // SECONDS_OF_DAY - seconds_ = seconds_ % SECONDS_OF_DAY - self.days += days_ - self.seconds += seconds_ - - seconds_ = microseconds_ // 1000000 - self.microseconds = microseconds_ % 1000000 - self.seconds += seconds_ - days_ = self.seconds // SECONDS_OF_DAY - self.seconds = self.seconds % SECONDS_OF_DAY - self.days += days_ - - fn __copyinit__(inout self, other: Self): - self.days = other.days - self.seconds = other.seconds - self.microseconds = other.microseconds - - fn __str__(self) -> String: - var mm = self.seconds // 60 - var ss = self.seconds % 60 - var hh = mm // 60 - mm = mm % 60 - var s = String(hh) + ":" + rjust(mm, 2, "0") + ":" + rjust(ss, 2, "0") - if self.days: - if abs(self.days) != 1: - s = String(self.days) + " days, " + s - else: - s = String(self.days) + " day, " + s - if self.microseconds: - s = s + rjust(self.microseconds, 6, "0") - return s - - fn total_seconds(self) -> Float64: - """Total seconds in the duration.""" - return ( - (self.days * 86400 + self.seconds) * 10**6 + self.microseconds - ) / 10**6 - - @always_inline - fn __add__(self, other: Self) -> Self: - return Self( - self.days + other.days, - self.seconds + other.seconds, - self.microseconds + other.microseconds, - ) - - fn __radd__(self, other: Self) -> Self: - return self.__add__(other) - - fn __sub__(self, other: Self) -> Self: - return Self( - self.days - other.days, - self.seconds - other.seconds, - self.microseconds - other.microseconds, - ) - - fn __rsub__(self, other: Self) -> Self: - return Self( - other.days - self.days, - other.seconds - self.seconds, - other.microseconds - self.microseconds, - ) - - fn __neg__(self) -> Self: - return Self(-self.days, -self.seconds, -self.microseconds) - - fn __pos__(self) -> Self: - return self - - def __abs__(self) -> Self: - if self.days < 0: - return -self - else: - return self - - @always_inline - fn __mul__(self, other: Int) -> Self: - return Self( - self.days * other, - self.seconds * other, - self.microseconds * other, - ) - - fn __rmul__(self, other: Int) -> Self: - return self.__mul__(other) - - fn _to_microseconds(self) -> Int: - return (self.days * SECONDS_OF_DAY + self.seconds) * 1000000 + self.microseconds - - fn __mod__(self, other: Self) -> Self: - var r = self._to_microseconds() % other._to_microseconds() - return Self(0, 0, r) - - fn __eq__(self, other: Self) -> Bool: - return ( - self.days == other.days - and self.seconds == other.seconds - and self.microseconds == other.microseconds - ) - - @always_inline - fn __le__(self, other: Self) -> Bool: - if self.days < other.days: - return True - elif self.days == other.days: - if self.seconds < other.seconds: - return True - elif ( - self.seconds == other.seconds - and self.microseconds <= other.microseconds - ): - return True - return False - - @always_inline - fn __lt__(self, other: Self) -> Bool: - if self.days < other.days: - return True - elif self.days == other.days: - if self.seconds < other.seconds: - return True - elif ( - self.seconds == other.seconds and self.microseconds < other.microseconds - ): - return True - return False - - fn __ge__(self, other: Self) -> Bool: - return not self.__lt__(other) - - fn __gt__(self, other: Self) -> Bool: - return not self.__le__(other) - - fn __bool__(self) -> Bool: - return self.days != 0 or self.seconds != 0 or self.microseconds != 0 - - -alias Min = TimeDelta(-99999999) -alias Max = TimeDelta(days=99999999) -alias Resolution = TimeDelta(microseconds=1) diff --git a/external/morrow/timezone.mojo b/external/morrow/timezone.mojo deleted file mode 100644 index 4da99163..00000000 --- a/external/morrow/timezone.mojo +++ /dev/null @@ -1,76 +0,0 @@ -from .util import rjust -from ._libc import c_localtime - -alias UTC_TZ = TimeZone(0, "UTC") - - -@value -struct TimeZone(Stringable): - var offset: Int - var name: String - - fn __init__(inout self, offset: Int, name: String = ""): - self.offset = offset - self.name = name - - fn __str__(self) -> String: - return self.name - - fn is_none(self) -> Bool: - return self.name == "None" - - @staticmethod - fn none() -> TimeZone: - return TimeZone(0, "None") - - @staticmethod - fn local() -> TimeZone: - var local_t = c_localtime(0) - return TimeZone(local_t.tm_gmtoff.to_int(), "local") - - @staticmethod - fn from_utc(utc_str: String) raises -> TimeZone: - if len(utc_str) == 0: - raise Error("utc_str is empty") - if utc_str == "utc" or utc_str == "UTC" or utc_str == "Z": - return TimeZone(0, "utc") - var p = 3 if len(utc_str) > 3 and utc_str[0:3] == "UTC" else 0 - - var sign = -1 if utc_str[p] == "-" else 1 - if utc_str[p] == "+" or utc_str[p] == "-": - p += 1 - - if ( - len(utc_str) < p + 2 - or not isdigit(ord(utc_str[p])) - or not isdigit(ord(utc_str[p + 1])) - ): - raise Error("utc_str format is invalid") - var hours: Int = atol(utc_str[p : p + 2]) - p += 2 - - var minutes: Int - if len(utc_str) <= p: - minutes = 0 - elif len(utc_str) == p + 3 and utc_str[p] == ":": - minutes = atol(utc_str[p + 1 : p + 3]) - elif len(utc_str) == p + 2 and isdigit(ord(utc_str[p])): - minutes = atol(utc_str[p : p + 2]) - else: - minutes = 0 - raise Error("utc_str format is invalid") - var offset: Int = sign * (hours * 3600 + minutes * 60) - return TimeZone(offset) - - fn format(self, sep: String = ":") -> String: - var sign: String - var offset_abs: Int - if self.offset < 0: - sign = "-" - offset_abs = -self.offset - else: - sign = "+" - offset_abs = self.offset - var hh = offset_abs // 3600 - var mm = offset_abs % 3600 - return sign + rjust(hh, 2, "0") + sep + rjust(mm, 2, "0") diff --git a/external/morrow/util.mojo b/external/morrow/util.mojo deleted file mode 100644 index 29c1e73c..00000000 --- a/external/morrow/util.mojo +++ /dev/null @@ -1,64 +0,0 @@ -from .constants import MAX_TIMESTAMP, MAX_TIMESTAMP_MS, MAX_TIMESTAMP_US -from .constants import _DAYS_IN_MONTH, _DAYS_BEFORE_MONTH - - -fn _is_leap(year: Int) -> Bool: - "year -> 1 if leap year, else 0." - return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0) - - -def _days_before_year(year: Int) -> Int: - "year -> number of days before January 1st of year." - var y = year - 1 - return y * 365 + y // 4 - y // 100 + y // 400 - - -def _days_in_month(year: Int, month: Int) -> Int: - "year, month -> number of days in that month in that year." - if month == 2 and _is_leap(year): - return 29 - return _DAYS_IN_MONTH[month] - - -def _days_before_month(year: Int, month: Int) -> Int: - "year, month -> number of days in year preceding first day of month." - if month > 2 and _is_leap(year): - return _DAYS_BEFORE_MONTH[month] + 1 - return _DAYS_BEFORE_MONTH[month] - - -@always_inline -def _ymd2ord(year: Int, month: Int, day: Int) -> Int: - "year, month, day -> ordinal, considering 01-Jan-0001 as day 1." - dim = _days_in_month(year, month) - return _days_before_year(year) + _days_before_month(year, month) + day - - -def normalize_timestamp(timestamp: Float64) -> Float64: - """Normalize millisecond and microsecond timestamps into normal timestamps.""" - if timestamp > MAX_TIMESTAMP: - if timestamp < MAX_TIMESTAMP_MS: - timestamp /= 1000 - elif timestamp < MAX_TIMESTAMP_US: - timestamp /= 1_000_000 - else: - raise Error( - "The specified timestamp is too large." - ) - return timestamp - - -fn _repeat_string(string: String, n: Int) -> String: - var result: String = "" - for _ in range(n): - result += string - return result - - -fn rjust(string: String, width: Int, fillchar: String = " ") -> String: - var extra = width - len(string) - return _repeat_string(fillchar, extra) + string - - -fn rjust(string: Int, width: Int, fillchar: String = " ") -> String: - return rjust(string, width, fillchar) diff --git a/recipes/recipe.yaml b/recipes/recipe.yaml index 1c7710fa..2693fcdb 100644 --- a/recipes/recipe.yaml +++ b/recipes/recipe.yaml @@ -20,6 +20,7 @@ requirements: run: - max >=24.5.0 - gojo == 0.1.9 + - small_time == 0.1.3 about: homepage: https://github.com/saviorand/lightbug_http