micromegas_transit/
dyn_string.rs1use crate::{
2 InProcSerialize, InProcSize, advance_window, read_consume_pod, string_codec::StringCodec,
3 write_any,
4};
5use anyhow::Result;
6
7#[derive(Debug)]
8pub struct LegacyDynString(pub String);
9
10impl InProcSerialize for LegacyDynString {
11 const IN_PROC_SIZE: InProcSize = InProcSize::Dynamic;
12
13 fn get_value_size(&self) -> Option<u32> {
14 Some(self.0.len() as u32)
15 }
16
17 fn write_value(&self, buffer: &mut Vec<u8>) {
18 buffer.extend_from_slice(self.0.as_bytes());
19 }
20
21 #[allow(unsafe_code)]
22 unsafe fn read_value(window: &[u8]) -> Self {
23 Self(String::from_utf8(window.to_vec()).unwrap())
24 }
25}
26
27#[derive(Debug)]
28pub struct DynString(pub String);
29
30impl InProcSerialize for DynString {
31 const IN_PROC_SIZE: InProcSize = InProcSize::Dynamic;
32
33 fn get_value_size(&self) -> Option<u32> {
34 let header_size = 1 + std::mem::size_of::<u32>() as u32 ;
37 let string_size = self.0.len() as u32;
38 Some(header_size + string_size)
39 }
40
41 fn write_value(&self, buffer: &mut Vec<u8>) {
42 let codec = StringCodec::Utf8 as u8;
43 write_any(buffer, &codec);
44 let len = self.0.len() as u32;
45 write_any(buffer, &len);
46 buffer.extend_from_slice(self.0.as_bytes());
47 }
48
49 #[allow(unsafe_code)]
50 unsafe fn read_value(mut window: &[u8]) -> Self {
51 let res = read_advance_string(&mut window).unwrap();
52 assert_eq!(window.len(), 0);
53 Self(res)
54 }
55}
56
57#[allow(unsafe_code, clippy::cast_ptr_alignment)]
59pub fn read_advance_string(window: &mut &[u8]) -> Result<String> {
60 unsafe {
61 let codec = StringCodec::try_from(read_consume_pod::<u8>(window))?;
62 let string_len_bytes: u32 = read_consume_pod(window);
63 let string_buffer = &window[0..(string_len_bytes as usize)];
64 *window = advance_window(window, string_len_bytes as usize);
65 match codec {
66 StringCodec::Ansi => {
67 Ok(String::from_utf8_lossy(string_buffer).to_string())
71 }
72 StringCodec::Wide => {
73 let ptr = string_buffer.as_ptr().cast::<u16>();
75 if !string_len_bytes.is_multiple_of(2) {
76 anyhow::bail!("wrong utf-16 buffer size");
77 }
78 let wide_slice = std::ptr::slice_from_raw_parts(ptr, string_len_bytes as usize / 2);
79 Ok(String::from_utf16_lossy(&*wide_slice))
80 }
81 StringCodec::Utf8 => Ok(String::from_utf8_lossy(string_buffer).to_string()),
82 }
83 }
84}