1use bytes::{Buf, BufMut};
7
8pub fn read_b_varchar(src: &mut impl Buf) -> Option<String> {
12 if src.remaining() < 1 {
13 return None;
14 }
15 let len = src.get_u8() as usize;
16 read_utf16_string(src, len)
17}
18
19pub fn read_us_varchar(src: &mut impl Buf) -> Option<String> {
23 if src.remaining() < 2 {
24 return None;
25 }
26 let len = src.get_u16_le() as usize;
27 read_utf16_string(src, len)
28}
29
30pub fn read_utf16_string(src: &mut impl Buf, char_count: usize) -> Option<String> {
32 let byte_count = char_count * 2;
33 if src.remaining() < byte_count {
34 return None;
35 }
36
37 let mut chars = Vec::with_capacity(char_count);
38 for _ in 0..char_count {
39 chars.push(src.get_u16_le());
40 }
41
42 String::from_utf16(&chars).ok()
43}
44
45pub fn write_b_varchar(dst: &mut impl BufMut, s: &str) {
47 let chars: Vec<u16> = s.encode_utf16().collect();
48 let len = chars.len().min(255) as u8;
49 dst.put_u8(len);
50 for &c in &chars[..len as usize] {
51 dst.put_u16_le(c);
52 }
53}
54
55pub fn write_us_varchar(dst: &mut impl BufMut, s: &str) {
57 let chars: Vec<u16> = s.encode_utf16().collect();
58 let len = chars.len().min(65535) as u16;
59 dst.put_u16_le(len);
60 for &c in &chars[..len as usize] {
61 dst.put_u16_le(c);
62 }
63}
64
65pub fn write_utf16_string(dst: &mut impl BufMut, s: &str) {
67 for c in s.encode_utf16() {
68 dst.put_u16_le(c);
69 }
70}
71
72pub fn read_null_terminated_ascii(src: &mut impl Buf) -> Option<String> {
74 let mut bytes = Vec::new();
75 while src.has_remaining() {
76 let b = src.get_u8();
77 if b == 0 {
78 break;
79 }
80 bytes.push(b);
81 }
82 String::from_utf8(bytes).ok()
83}
84
85#[must_use]
87pub fn utf16_byte_len(s: &str) -> usize {
88 s.encode_utf16().count() * 2
89}
90
91#[cfg(not(feature = "std"))]
92use alloc::string::String;
93#[cfg(not(feature = "std"))]
94use alloc::vec::Vec;
95
96#[cfg(test)]
97#[allow(clippy::unwrap_used)]
98mod tests {
99 use super::*;
100 use bytes::BytesMut;
101
102 #[test]
103 fn test_b_varchar_roundtrip() {
104 let original = "Hello, 世界!";
105 let mut buf = BytesMut::new();
106 write_b_varchar(&mut buf, original);
107
108 let mut cursor = buf.freeze();
109 let decoded = read_b_varchar(&mut cursor).unwrap();
110 assert_eq!(decoded, original);
111 }
112
113 #[test]
114 fn test_us_varchar_roundtrip() {
115 let original = "Test string with Unicode: αβγ";
116 let mut buf = BytesMut::new();
117 write_us_varchar(&mut buf, original);
118
119 let mut cursor = buf.freeze();
120 let decoded = read_us_varchar(&mut cursor).unwrap();
121 assert_eq!(decoded, original);
122 }
123
124 #[test]
125 fn test_utf16_byte_len() {
126 assert_eq!(utf16_byte_len("Hello"), 10);
127 assert_eq!(utf16_byte_len("世界"), 4);
128 }
129}