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