use serde::Serialize;
use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, Unaligned};
use crate::tag::tagdata::TextData;
#[repr(C)]
#[derive(FromBytes, KnownLayout, Unaligned, Immutable)]
struct Layout {
signature: [u8; 4],
_reserved: [u8; 4],
text: [u8],
}
#[repr(C)]
#[derive(FromBytes, IntoBytes, KnownLayout, Unaligned, Immutable)]
struct WriteLayout {
signature: [u8; 4],
_reserved: [u8; 4],
}
impl WriteLayout {
pub fn new() -> Self {
Self {
signature: super::DataSignature::TextData.into(),
_reserved: [0; 4],
}
}
}
#[derive(Serialize)]
pub struct TextType {
text: String,
}
impl From<&TextData> for TextType {
fn from(text: &TextData) -> Self {
let layout = Layout::ref_from_bytes(&text.0).unwrap();
let bytes = &layout.text;
let end = bytes.iter().position(|&b| b == 0).unwrap_or(bytes.len());
let text = String::from_utf8_lossy(&bytes[..end]).into_owned();
Self { text }
}
}
impl TextData {
pub fn set_text(&mut self, text: &str) {
if !text.is_ascii() {
panic!("TextData only supports ASCII text");
}
let mut buf = Vec::with_capacity(std::mem::size_of::<WriteLayout>() + text.len() + 1);
buf.extend_from_slice(WriteLayout::new().as_bytes());
buf.extend_from_slice(text.trim_end_matches('\0').as_bytes());
buf.push(0); self.0 = buf;
}
}