1// Copyright 2025 International Digital Economy Academy
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15///|
16type Udp
17
18///|
19pub impl trait ToHandle {
to_handle(Self) -> Handle
of_handle(Handle) -> Self
close(Self, (Self) -> Unit) -> Unit
is_closing(Self) -> Bool
loop_(Self) -> Loop
}
ToHandle for type Udp
Udp with to_handle(self : type Udp
Udp) -> type Handle
Handle = "%identity"
20
21///|
22pub impl trait ToHandle {
to_handle(Self) -> Handle
of_handle(Handle) -> Self
close(Self, (Self) -> Unit) -> Unit
is_closing(Self) -> Bool
loop_(Self) -> Loop
}
ToHandle for type Udp
Udp with of_handle(self : type Handle
Handle) -> type Udp
Udp = "%identity"
23
24///|
25extern "c" fn uv_udp_make() -> type Udp
Udp = "moonbit_uv_udp_make"
26
27///|
28extern "c" fn uv_udp_init(uv : type Loop Bytes
Loop, udp : type Udp
Udp) -> Int
Int = "moonbit_uv_udp_init"
29
30///|
31pub fn type Udp
Udp::(uv : Loop) -> Udp raise Errno
new(Loop
uv : type Loop Bytes
Loop) -> type Udp
Udp raise type! Errno Status
Errno {
32 let Udp
udp = () -> Udp
uv_udp_make()
33 let Int
result = (uv : Loop, udp : Udp) -> Int
uv_udp_init(Loop
uv, Udp
udp)
34 if Int
result (self_ : Int, other : Int) -> Bool
< 0 {
35 raise type! Errno Status
Errno::(errno : Int) -> Errno
of_int(Int
result)
36 }
37 Udp
udp
38}
39
40///|
41extern "c" fn uv_udp_connect(handle : type Udp
Udp, addr : type Sockaddr Bytes
Sockaddr) -> Int
Int = "moonbit_uv_udp_connect"
42
43///|
44pub fn[Sockaddr : trait ToSockaddr {
to_sockaddr(self : Self) -> Sockaddr
ip_name(self : Self) -> String raise Errno
}
ToSockaddr] type Udp
Udp::(self : Udp, addr : Sockaddr) -> Unit raise Errno
connect(
45 Udp
self : type Udp
Udp,
46 Sockaddr
addr : type parameter Sockaddr
Sockaddr
47) -> Unit
Unit raise type! Errno Status
Errno {
48 let Int
result = (handle : Udp, addr : Sockaddr) -> Int
uv_udp_connect(Udp
self, Sockaddr
addr.(Sockaddr) -> Sockaddr
to_sockaddr())
49 if Int
result (self_ : Int, other : Int) -> Bool
< 0 {
50 raise type! Errno Status
Errno::(errno : Int) -> Errno
of_int(Int
result)
51 }
52}
53
54///|
55extern "c" fn uv_udp_bind(handle : type Udp
Udp, addr : type Sockaddr Bytes
Sockaddr, flags : UInt
UInt) -> Int
Int = "moonbit_uv_udp_bind"
56
57///|
58pub fn[Sockaddr : trait ToSockaddr {
to_sockaddr(self : Self) -> Sockaddr
ip_name(self : Self) -> String raise Errno
}
ToSockaddr] type Udp
Udp::(self : Udp, addr : Sockaddr, flags : UdpFlags) -> Unit raise Errno
bind(
59 Udp
self : type Udp
Udp,
60 Sockaddr
addr : type parameter Sockaddr
Sockaddr,
61 UdpFlags
flags : type UdpFlags UInt
UdpFlags
62) -> Unit
Unit raise type! Errno Status
Errno {
63 let Int
result = (handle : Udp, addr : Sockaddr, flags : UInt) -> Int
uv_udp_bind(Udp
self, Sockaddr
addr.(Sockaddr) -> Sockaddr
to_sockaddr(), UdpFlags
flags.(self : UdpFlags) -> UInt
Convert newtype to its underlying type, automatically derived.
inner())
64 if Int
result (self_ : Int, other : Int) -> Bool
< 0 {
65 raise type! Errno Status
Errno::(errno : Int) -> Errno
of_int(Int
result)
66 }
67}
68
69///|
70type UdpSend
71
72///|
73pub impl trait ToReq {
to_req(Self) -> Req
}
ToReq for type UdpSend
UdpSend with to_req(self : type UdpSend
UdpSend) -> type Req
Req = "%identity"
74
75///|
76extern "c" fn uv_udp_send_make() -> type UdpSend
UdpSend = "moonbit_uv_udp_send_make"
77
78///|
79extern "c" fn uv_udp_send(
80 send : type UdpSend
UdpSend,
81 udp : type Udp
Udp,
82 bufs_base : type FixedArray[A]
FixedArray[Bytes
Bytes],
83 bufs_offset : type FixedArray[A]
FixedArray[Int
Int],
84 bufs_length : type FixedArray[A]
FixedArray[Int
Int],
85 addr : @c.Nullable[type Sockaddr Bytes
Sockaddr],
86 cb : (type UdpSend
UdpSend, Int
Int) -> Unit
Unit
87) -> Int
Int = "moonbit_uv_udp_send"
88
89///|
90pub fn[Sockaddr : trait ToSockaddr {
to_sockaddr(self : Self) -> Sockaddr
ip_name(self : Self) -> String raise Errno
}
ToSockaddr] type Udp
Udp::(self : Udp, data : Array[@bytes.View], send_cb : () -> Unit, error_cb : (Errno) -> Unit, addr? : Sockaddr) -> UdpSend raise Errno
send(
91 Udp
self : type Udp
Udp,
92 Array[@bytes.View]
data : type Array[T]
An Array is a collection of values that supports random access and can
grow in size.
Array[type @bytes.View
A @bytes.View represents a view into a section of a Bytes without copying the data.
Example
let bs = b"\x00\x01\x02\x03\x04\x05"
let bv = bs[1:4]
assert_eq(bv.length(), 3)
assert_eq(bv[0], b'\x01')
assert_eq(bv[1], b'\x02')
assert_eq(bv[2], b'\x03')
@bytes.View],
93 () -> Unit
send_cb : () -> Unit
Unit,
94 (Errno) -> Unit
error_cb : (type! Errno Status
Errno) -> Unit
Unit,
95 Sockaddr?
addr? : type parameter Sockaddr
Sockaddr
96) -> type UdpSend
UdpSend raise type! Errno Status
Errno {
97 fn (UdpSend, Int) -> Unit
cb(_ : type UdpSend
UdpSend, Int
status : Int
Int) {
98 if Int
status (self_ : Int, other : Int) -> Bool
< 0 {
99 (Errno) -> Unit
error_cb(type! Errno Status
Errno::(errno : Int) -> Errno
of_int(Int
status))
100 } else {
101 () -> Unit
send_cb()
102 }
103 }
104
105 let UdpSend
req = () -> UdpSend
uv_udp_send_make()
106 let Int
bufs_size = Array[@bytes.View]
data.(self : Array[@bytes.View]) -> Int
Returns the number of elements in the array.
Parameters:
array : The array whose length is to be determined.
Returns the number of elements in the array as an integer.
Example:
let arr = [1, 2, 3]
inspect(arr.length(), content="3")
let empty : Array[Int] = []
inspect(empty.length(), content="0")
length()
107 let FixedArray[Bytes]
bufs_base : type FixedArray[A]
FixedArray[Bytes
Bytes] = type FixedArray[A]
FixedArray::(len : Int, init : Bytes) -> FixedArray[Bytes]
Creates a new fixed-size array with the specified length, initializing all
elements with the given value.
Parameters:
length : The length of the array to create. Must be non-negative.
initial_value : The value used to initialize all elements in the array.
Returns a new fixed-size array of type FixedArray[T] with length
elements, where each element is initialized to initial_value.
Throws a panic if length is negative.
Example:
let arr = FixedArray::make(3, 42)
inspect(arr[0], content="42")
inspect(arr.length(), content="3")
WARNING: A common pitfall is creating with the same initial value, for example:
let two_dimension_array = FixedArray::make(10, FixedArray::make(10, 0))
two_dimension_array[0][5] = 10
assert_eq(two_dimension_array[5][5], 10)
This is because all the cells reference to the same object (the FixedArray[Int] in this case).
One should use makei() instead which creates an object for each index.
make(Int
bufs_size, [])
108 let FixedArray[Int]
bufs_offset = type FixedArray[A]
FixedArray::(len : Int, init : Int) -> FixedArray[Int]
Creates a new fixed-size array with the specified length, initializing all
elements with the given value.
Parameters:
length : The length of the array to create. Must be non-negative.
initial_value : The value used to initialize all elements in the array.
Returns a new fixed-size array of type FixedArray[T] with length
elements, where each element is initialized to initial_value.
Throws a panic if length is negative.
Example:
let arr = FixedArray::make(3, 42)
inspect(arr[0], content="42")
inspect(arr.length(), content="3")
WARNING: A common pitfall is creating with the same initial value, for example:
let two_dimension_array = FixedArray::make(10, FixedArray::make(10, 0))
two_dimension_array[0][5] = 10
assert_eq(two_dimension_array[5][5], 10)
This is because all the cells reference to the same object (the FixedArray[Int] in this case).
One should use makei() instead which creates an object for each index.
make(Int
bufs_size, 0)
109 let FixedArray[Int]
bufs_length = type FixedArray[A]
FixedArray::(len : Int, init : Int) -> FixedArray[Int]
Creates a new fixed-size array with the specified length, initializing all
elements with the given value.
Parameters:
length : The length of the array to create. Must be non-negative.
initial_value : The value used to initialize all elements in the array.
Returns a new fixed-size array of type FixedArray[T] with length
elements, where each element is initialized to initial_value.
Throws a panic if length is negative.
Example:
let arr = FixedArray::make(3, 42)
inspect(arr[0], content="42")
inspect(arr.length(), content="3")
WARNING: A common pitfall is creating with the same initial value, for example:
let two_dimension_array = FixedArray::make(10, FixedArray::make(10, 0))
two_dimension_array[0][5] = 10
assert_eq(two_dimension_array[5][5], 10)
This is because all the cells reference to the same object (the FixedArray[Int] in this case).
One should use makei() instead which creates an object for each index.
make(Int
bufs_size, 0)
110 for Int
i in Int
0..<Array[@bytes.View]
data.(self : Array[@bytes.View]) -> Int
Returns the number of elements in the array.
Parameters:
array : The array whose length is to be determined.
Returns the number of elements in the array as an integer.
Example:
let arr = [1, 2, 3]
inspect(arr.length(), content="3")
let empty : Array[Int] = []
inspect(empty.length(), content="0")
length() {
111 FixedArray[Bytes]
bufs_base(FixedArray[Bytes], Int, Bytes) -> Unit
Sets a value at the specified index in a fixed-size array. The original value
at that index is overwritten.
Parameters:
array : The fixed-size array to modify.
index : The position in the array where the value will be set.
value : The new value to assign at the specified index.
Throws a runtime error if the index is out of bounds (less than 0 or greater
than or equal to the length of the array).
Example:
let arr = [1, 2, 3]
arr[1] = 42
inspect(arr, content="[1, 42, 3]")
[i] = Array[@bytes.View]
data(Array[@bytes.View], Int) -> @bytes.View
Retrieves an element from the array at the specified index.
Parameters:
array : The array to get the element from.
index : The position in the array from which to retrieve the element.
Returns the element at the specified index.
Throws a panic if the index is negative or greater than or equal to the
length of the array.
Example:
let arr = [1, 2, 3]
inspect(arr[1], content="2")
[i].(self : @bytes.View) -> Bytes
Retrieves the underlying Bytes from a View.
data()
112 FixedArray[Int]
bufs_offset(FixedArray[Int], Int, Int) -> Unit
Sets a value at the specified index in a fixed-size array. The original value
at that index is overwritten.
Parameters:
array : The fixed-size array to modify.
index : The position in the array where the value will be set.
value : The new value to assign at the specified index.
Throws a runtime error if the index is out of bounds (less than 0 or greater
than or equal to the length of the array).
Example:
let arr = [1, 2, 3]
arr[1] = 42
inspect(arr, content="[1, 42, 3]")
[i] = Array[@bytes.View]
data(Array[@bytes.View], Int) -> @bytes.View
Retrieves an element from the array at the specified index.
Parameters:
array : The array to get the element from.
index : The position in the array from which to retrieve the element.
Returns the element at the specified index.
Throws a panic if the index is negative or greater than or equal to the
length of the array.
Example:
let arr = [1, 2, 3]
inspect(arr[1], content="2")
[i].(self : @bytes.View) -> Int
Retrieves the start index of the view.
start_offset()
113 FixedArray[Int]
bufs_length(FixedArray[Int], Int, Int) -> Unit
Sets a value at the specified index in a fixed-size array. The original value
at that index is overwritten.
Parameters:
array : The fixed-size array to modify.
index : The position in the array where the value will be set.
value : The new value to assign at the specified index.
Throws a runtime error if the index is out of bounds (less than 0 or greater
than or equal to the length of the array).
Example:
let arr = [1, 2, 3]
arr[1] = 42
inspect(arr, content="[1, 42, 3]")
[i] = Array[@bytes.View]
data(Array[@bytes.View], Int) -> @bytes.View
Retrieves an element from the array at the specified index.
Parameters:
array : The array to get the element from.
index : The position in the array from which to retrieve the element.
Returns the element at the specified index.
Throws a panic if the index is negative or greater than or equal to the
length of the array.
Example:
let arr = [1, 2, 3]
inspect(arr[1], content="2")
[i].(self : @bytes.View) -> Int
Returns the number of bytes in the view.
Parameters:
bytes_view : The view of a byte sequence.
Returns an integer representing the length of the view.
Example:
let bytes = b"\x00\x01\x02\x03\x04"
let view = bytes[2:4]
inspect(view.length(), content="2")
length()
114 }
115 let Int
result = (send : UdpSend, udp : Udp, bufs_base : FixedArray[Bytes], bufs_offset : FixedArray[Int], bufs_length : FixedArray[Int], addr : ?, cb : (UdpSend, Int) -> Unit) -> Int
uv_udp_send(
116 UdpSend
req,
117 Udp
self,
118 FixedArray[Bytes]
bufs_base,
119 FixedArray[Int]
bufs_offset,
120 FixedArray[Int]
bufs_length,
121 (Sockaddr?) -> ?
@c.Nullable::of(Sockaddr?
addr.(self : Sockaddr?, f : (Sockaddr) -> Sockaddr) -> Sockaddr?
Maps the value of an Option using a provided function.
Example
let a = Some(5)
assert_eq(a.map(fn(x){ x * 2 }), Some(10))
let b = None
assert_eq(b.map(fn(x){ x * 2 }), None)
map(type parameter
Sockaddr(Sockaddr) -> Sockaddr
::to_sockaddr)),
122 (UdpSend, Int) -> Unit
cb,
123 )
124 if Int
result (self_ : Int, other : Int) -> Bool
< 0 {
125 raise type! Errno Status
Errno::(errno : Int) -> Errno
of_int(Int
result)
126 }
127 return UdpSend
req
128}
129
130///|
131extern "c" fn uv_udp_recv_start(
132 udp : type Udp
Udp,
133 alloc_cb : (type Handle
Handle, UInt64
UInt64, @c.Pointer[Int
Int], @c.Pointer[Int
Int]) -> Bytes
Bytes,
134 recv_cb : (type Udp
Udp, Int64
Int64, Bytes
Bytes?, Int
Int, Int
Int, type Sockaddr Bytes
Sockaddr, UInt
UInt) -> Unit
Unit
135) -> Int
Int = "moonbit_uv_udp_recv_start"
136
137///|
138pub fn type Udp
Udp::(self : Udp, alloc_cb : (Handle, Int) -> @bytes.View, read_cb : (Udp, Int, @bytes.View, Sockaddr, UdpFlags) -> Unit, error_cb : (Udp, Errno) -> Unit) -> Unit raise Errno
recv_start(
139 Udp
self : type Udp
Udp,
140 (Handle, Int) -> @bytes.View
alloc_cb : (type Handle
Handle, Int
Int) -> type @bytes.View
A @bytes.View represents a view into a section of a Bytes without copying the data.
Example
let bs = b"\x00\x01\x02\x03\x04\x05"
let bv = bs[1:4]
assert_eq(bv.length(), 3)
assert_eq(bv[0], b'\x01')
assert_eq(bv[1], b'\x02')
assert_eq(bv[2], b'\x03')
@bytes.View,
141 (Udp, Int, @bytes.View, Sockaddr, UdpFlags) -> Unit
read_cb : (type Udp
Udp, Int
Int, type @bytes.View
A @bytes.View represents a view into a section of a Bytes without copying the data.
Example
let bs = b"\x00\x01\x02\x03\x04\x05"
let bv = bs[1:4]
assert_eq(bv.length(), 3)
assert_eq(bv[0], b'\x01')
assert_eq(bv[1], b'\x02')
assert_eq(bv[2], b'\x03')
@bytes.View, type Sockaddr Bytes
Sockaddr, type UdpFlags UInt
UdpFlags) -> Unit
Unit,
142 (Udp, Errno) -> Unit
error_cb : (type Udp
Udp, type! Errno Status
Errno) -> Unit
Unit
143) -> Unit
Unit raise type! Errno Status
Errno {
144 fn (Handle, UInt64, ?, ?) -> Bytes
uv_alloc_cb(
145 Handle
handle : type Handle
Handle,
146 UInt64
suggested_size : UInt64
UInt64,
147 ?
buf_offset : @c.Pointer[Int
Int],
148 ?
buf_length : @c.Pointer[Int
Int]
149 ) -> Bytes
Bytes {
150 let @bytes.View
bytes = (Handle, Int) -> @bytes.View
alloc_cb(Handle
handle, UInt64
suggested_size.(self : UInt64) -> Int
Converts an unsigned 64-bit integer to a 32-bit signed integer. The
conversion truncates the value to fit within the 32-bit range, possibly
losing information if the input value is too large.
Parameters:
self : The unsigned 64-bit integer to be converted.
Returns a 32-bit signed integer representing the lower 32 bits of the input
value. If the input value is larger than the maximum value of a 32-bit signed
integer (2147483647), the result will be the truncated value interpreted as a
signed integer.
Example:
let a = 42UL
inspect(a.to_int(), content="42")
let b = 18446744073709551615UL // max value of UInt64
inspect(b.to_int(), content="-1") // truncated to 32 bits
to_int())
151 ?
buf_offset[0] = @bytes.View
bytes.(self : @bytes.View) -> Int
Retrieves the start index of the view.
start_offset()
152 ?
buf_length[0] = @bytes.View
bytes.(self : @bytes.View) -> Int
Returns the number of bytes in the view.
Parameters:
bytes_view : The view of a byte sequence.
Returns an integer representing the length of the view.
Example:
let bytes = b"\x00\x01\x02\x03\x04"
let view = bytes[2:4]
inspect(view.length(), content="2")
length()
153 return @bytes.View
bytes.(self : @bytes.View) -> Bytes
Retrieves the underlying Bytes from a View.
data()
154 }
155
156 fn (Udp, Int64, Bytes?, Int, Int, Sockaddr, UInt) -> Unit
uv_recv_cb(
157 Udp
udp : type Udp
Udp,
158 Int64
count : Int64
Int64,
159 Bytes?
buf_data : Bytes
Bytes?,
160 Int
buf_offset : Int
Int,
161 Int
buf_length : Int
Int,
162 Sockaddr
sockaddr : type Sockaddr Bytes
Sockaddr,
163 UInt
flags : UInt
UInt
164 ) -> Unit
Unit {
165 if Int64
count (self_ : Int64, other : Int64) -> Bool
< 0 {
166 (Udp, Errno) -> Unit
error_cb(Udp
udp, type! Errno Status
Errno::(errno : Int) -> Errno
of_int(Int64
count.(self : Int64) -> Int
Converts a 64-bit signed integer to a 32-bit signed integer by truncating
higher bits.
Parameters:
value : The 64-bit signed integer (Int64) to be converted.
Returns a 32-bit signed integer (Int). Note that values outside the range
of 32-bit integers will be truncated, potentially leading to loss of
information.
Example:
let small = 42L
let big = 2147483648L // 2^31
inspect(small.to_int(), content="42")
inspect(big.to_int(), content="-2147483648") // Truncated to Int.min_value
to_int()))
167 } else {
168 (Udp, Int, @bytes.View, Sockaddr, UdpFlags) -> Unit
read_cb(
169 Udp
udp,
170 Int64
count.(self : Int64) -> Int
Converts a 64-bit signed integer to a 32-bit signed integer by truncating
higher bits.
Parameters:
value : The 64-bit signed integer (Int64) to be converted.
Returns a 32-bit signed integer (Int). Note that values outside the range
of 32-bit integers will be truncated, potentially leading to loss of
information.
Example:
let small = 42L
let big = 2147483648L // 2^31
inspect(small.to_int(), content="42")
inspect(big.to_int(), content="-2147483648") // Truncated to Int.min_value
to_int(),
171 Bytes?
buf_data.(self : Bytes?) -> Bytes
Extract the value in Some.
If the value is None, it throws a panic.
unwrap()[Int
buf_offset:Int
buf_length],
172 Sockaddr
sockaddr,
173 (UInt) -> UdpFlags
UdpFlags(UInt
flags),
174 )
175 }
176 }
177
178 let Int
result = (udp : Udp, alloc_cb : (Handle, UInt64, ?, ?) -> Bytes, recv_cb : (Udp, Int64, Bytes?, Int, Int, Sockaddr, UInt) -> Unit) -> Int
uv_udp_recv_start(Udp
self, (Handle, UInt64, ?, ?) -> Bytes
uv_alloc_cb, (Udp, Int64, Bytes?, Int, Int, Sockaddr, UInt) -> Unit
uv_recv_cb)
179 if Int
result (self_ : Int, other : Int) -> Bool
< 0 {
180 raise type! Errno Status
Errno::(errno : Int) -> Errno
of_int(Int
result)
181 }
182}
183
184///|
185extern "c" fn uv_udp_recv_stop(udp : type Udp
Udp) -> Int
Int = "moonbit_uv_udp_recv_stop"
186
187///|
188pub fn type Udp
Udp::(self : Udp) -> Unit raise Errno
recv_stop(Udp
self : type Udp
Udp) -> Unit
Unit raise type! Errno Status
Errno {
189 let Int
result = (udp : Udp) -> Int
uv_udp_recv_stop(Udp
self)
190 if Int
result (self_ : Int, other : Int) -> Bool
< 0 {
191 raise type! Errno Status
Errno::(errno : Int) -> Errno
of_int(Int
result)
192 }
193}
194
195///|
196type UdpFlags UInt
UInt
197
198///|
199pub fn type UdpFlags UInt
UdpFlags::() -> UdpFlags
new() -> type UdpFlags UInt
UdpFlags {
200 (UInt) -> UdpFlags
UdpFlags(0)
201}
202