- SSOT using profiles (aliases/packages via nyash.toml), AST prelude merge - Parser/member guards; Builder pin/PHI and instance→function rewrite (dev on) - VM refactors (handlers split) and JSON roundtrip/nested stabilization - CURRENT_TASK.md updated with scope and acceptance criteria Notes: dev-only guards remain togglable via env; no default behavior changes for prod.
130 lines
3.9 KiB
Rust
130 lines
3.9 KiB
Rust
//! TLV (Type-Length-Value) serialization helpers
|
|
|
|
use crate::constants::*;
|
|
|
|
pub fn write_tlv_result(payloads: &[(u8, &[u8])], result: *mut u8, result_len: *mut usize) -> i32 {
|
|
if result_len.is_null() {
|
|
return E_ARGS;
|
|
}
|
|
let mut buf: Vec<u8> =
|
|
Vec::with_capacity(4 + payloads.iter().map(|(_, p)| 4 + p.len()).sum::<usize>());
|
|
buf.extend_from_slice(&1u16.to_le_bytes());
|
|
buf.extend_from_slice(&(payloads.len() as u16).to_le_bytes());
|
|
for (tag, payload) in payloads {
|
|
buf.push(*tag);
|
|
buf.push(0);
|
|
buf.extend_from_slice(&(payload.len() as u16).to_le_bytes());
|
|
buf.extend_from_slice(payload);
|
|
}
|
|
unsafe {
|
|
let needed = buf.len();
|
|
if result.is_null() || *result_len < needed {
|
|
*result_len = needed;
|
|
return E_SHORT;
|
|
}
|
|
std::ptr::copy_nonoverlapping(buf.as_ptr(), result, needed);
|
|
*result_len = needed;
|
|
}
|
|
OK
|
|
}
|
|
|
|
pub fn write_u32(v: u32, result: *mut u8, result_len: *mut usize) -> i32 {
|
|
if result_len.is_null() {
|
|
return E_ARGS;
|
|
}
|
|
unsafe {
|
|
if result.is_null() || *result_len < 4 {
|
|
*result_len = 4;
|
|
return E_SHORT;
|
|
}
|
|
let b = v.to_le_bytes();
|
|
std::ptr::copy_nonoverlapping(b.as_ptr(), result, 4);
|
|
*result_len = 4;
|
|
}
|
|
OK
|
|
}
|
|
|
|
pub fn write_tlv_void(result: *mut u8, result_len: *mut usize) -> i32 {
|
|
// Align with common helpers: use tag=9 for void/host-handle-like empty
|
|
write_tlv_result(&[(9u8, &[])], result, result_len)
|
|
}
|
|
|
|
pub fn write_tlv_i64(v: i64, result: *mut u8, result_len: *mut usize) -> i32 {
|
|
write_tlv_result(&[(3u8, &v.to_le_bytes())], result, result_len)
|
|
}
|
|
|
|
pub fn write_tlv_bool(v: bool, result: *mut u8, result_len: *mut usize) -> i32 {
|
|
write_tlv_result(&[(1u8, &[if v { 1u8 } else { 0u8 }])], result, result_len)
|
|
}
|
|
|
|
pub fn write_tlv_handle(
|
|
type_id: u32,
|
|
instance_id: u32,
|
|
result: *mut u8,
|
|
result_len: *mut usize,
|
|
) -> i32 {
|
|
let mut payload = Vec::with_capacity(8);
|
|
payload.extend_from_slice(&type_id.to_le_bytes());
|
|
payload.extend_from_slice(&instance_id.to_le_bytes());
|
|
write_tlv_result(&[(8u8, &payload)], result, result_len)
|
|
}
|
|
|
|
pub fn write_tlv_string(s: &str, result: *mut u8, result_len: *mut usize) -> i32 {
|
|
write_tlv_result(&[(6u8, s.as_bytes())], result, result_len)
|
|
}
|
|
|
|
pub fn read_arg_string(args: *const u8, args_len: usize, n: usize) -> Option<String> {
|
|
if args.is_null() || args_len < 4 {
|
|
return None;
|
|
}
|
|
let buf = unsafe { std::slice::from_raw_parts(args, args_len) };
|
|
let mut off = 4usize;
|
|
for i in 0..=n {
|
|
if buf.len() < off + 4 {
|
|
return None;
|
|
}
|
|
let tag = buf[off];
|
|
let size = u16::from_le_bytes([buf[off + 2], buf[off + 3]]) as usize;
|
|
if buf.len() < off + 4 + size {
|
|
return None;
|
|
}
|
|
if i == n {
|
|
if tag != 6 {
|
|
return None;
|
|
}
|
|
let s = String::from_utf8_lossy(&buf[off + 4..off + 4 + size]).to_string();
|
|
return Some(s);
|
|
}
|
|
off += 4 + size;
|
|
}
|
|
None
|
|
}
|
|
|
|
pub fn read_arg_i64(args: *const u8, args_len: usize, n: usize) -> Option<i64> {
|
|
if args.is_null() || args_len < 4 {
|
|
return None;
|
|
}
|
|
let buf = unsafe { std::slice::from_raw_parts(args, args_len) };
|
|
let mut off = 4usize;
|
|
for i in 0..=n {
|
|
if buf.len() < off + 4 {
|
|
return None;
|
|
}
|
|
let tag = buf[off];
|
|
let size = u16::from_le_bytes([buf[off + 2], buf[off + 3]]) as usize;
|
|
if buf.len() < off + 4 + size {
|
|
return None;
|
|
}
|
|
if i == n {
|
|
if tag != 3 || size != 8 {
|
|
return None;
|
|
}
|
|
let mut b = [0u8; 8];
|
|
b.copy_from_slice(&buf[off + 4..off + 12]);
|
|
return Some(i64::from_le_bytes(b));
|
|
}
|
|
off += 4 + size;
|
|
}
|
|
None
|
|
}
|