smokes: add curated LLVM runner; archive legacy smokes; PHI-off unified across Bridge/Builder; LLVM resolver tracing; minimal Throw lowering; config env getters; dev profile and root cleaner; docs updated; CI workflow runs curated LLVM (PHI-on/off)
This commit is contained in:
@ -1,12 +1,15 @@
|
||||
//! Nyash FileBox Plugin - BID-FFI v1 Implementation
|
||||
//!
|
||||
//!
|
||||
//! Provides file I/O operations as a Nyash plugin
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::os::raw::c_char;
|
||||
// std::ptr削除(未使用)
|
||||
use std::sync::{Mutex, atomic::{AtomicU32, Ordering}};
|
||||
use std::io::{Read, Write, Seek, SeekFrom};
|
||||
use std::io::{Read, Seek, SeekFrom, Write};
|
||||
use std::sync::{
|
||||
atomic::{AtomicU32, Ordering},
|
||||
Mutex,
|
||||
};
|
||||
|
||||
// ============ FFI Types ============
|
||||
|
||||
@ -37,7 +40,7 @@ const NYB_E_PLUGIN_ERROR: i32 = -5;
|
||||
const NYB_E_INVALID_HANDLE: i32 = -8;
|
||||
|
||||
// ============ Method IDs ============
|
||||
const METHOD_BIRTH: u32 = 0; // Constructor
|
||||
const METHOD_BIRTH: u32 = 0; // Constructor
|
||||
const METHOD_OPEN: u32 = 1;
|
||||
const METHOD_READ: u32 = 2;
|
||||
const METHOD_WRITE: u32 = 3;
|
||||
@ -45,20 +48,19 @@ const METHOD_CLOSE: u32 = 4;
|
||||
const METHOD_EXISTS: u32 = 5;
|
||||
const METHOD_COPY_FROM: u32 = 7; // New: copyFrom(other: Handle)
|
||||
const METHOD_CLONE_SELF: u32 = 8; // New: cloneSelf() -> Handle
|
||||
const METHOD_FINI: u32 = u32::MAX; // Destructor
|
||||
const METHOD_FINI: u32 = u32::MAX; // Destructor
|
||||
|
||||
// ============ FileBox Instance ============
|
||||
struct FileBoxInstance {
|
||||
file: Option<std::fs::File>,
|
||||
path: String,
|
||||
buffer: Option<Vec<u8>>, // プラグインが管理するバッファ
|
||||
buffer: Option<Vec<u8>>, // プラグインが管理するバッファ
|
||||
}
|
||||
|
||||
// グローバルインスタンス管理(実際の実装ではより安全な方法を使用)
|
||||
use once_cell::sync::Lazy;
|
||||
static INSTANCES: Lazy<Mutex<HashMap<u32, FileBoxInstance>>> = Lazy::new(|| {
|
||||
Mutex::new(HashMap::new())
|
||||
});
|
||||
static INSTANCES: Lazy<Mutex<HashMap<u32, FileBoxInstance>>> =
|
||||
Lazy::new(|| Mutex::new(HashMap::new()));
|
||||
|
||||
// ホスト関数テーブルは使用しない(Host VTable廃止)
|
||||
|
||||
@ -70,7 +72,7 @@ static INSTANCE_COUNTER: AtomicU32 = AtomicU32::new(1);
|
||||
/// ABI version
|
||||
#[no_mangle]
|
||||
pub extern "C" fn nyash_plugin_abi() -> u32 {
|
||||
1 // BID-1 support
|
||||
1 // BID-1 support
|
||||
}
|
||||
|
||||
/// Plugin initialization (optional - global setup)
|
||||
@ -119,11 +121,14 @@ pub extern "C" fn nyash_plugin_invoke(
|
||||
// 新しいインスタンスを作成
|
||||
let instance_id = INSTANCE_COUNTER.fetch_add(1, Ordering::Relaxed);
|
||||
if let Ok(mut map) = INSTANCES.lock() {
|
||||
map.insert(instance_id, FileBoxInstance {
|
||||
file: None,
|
||||
path: String::new(),
|
||||
buffer: None,
|
||||
});
|
||||
map.insert(
|
||||
instance_id,
|
||||
FileBoxInstance {
|
||||
file: None,
|
||||
path: String::new(),
|
||||
buffer: None,
|
||||
},
|
||||
);
|
||||
} else {
|
||||
return NYB_E_PLUGIN_ERROR;
|
||||
}
|
||||
@ -149,7 +154,9 @@ pub extern "C" fn nyash_plugin_invoke(
|
||||
match tlv_parse_two_strings(args) {
|
||||
Ok((path, mode)) => {
|
||||
// Preflight for Void TLV: header(4) + entry(4)
|
||||
if preflight(_result, _result_len, 8) { return NYB_E_SHORT_BUFFER; }
|
||||
if preflight(_result, _result_len, 8) {
|
||||
return NYB_E_SHORT_BUFFER;
|
||||
}
|
||||
log_info(&format!("OPEN path='{}' mode='{}'", path, mode));
|
||||
if let Ok(mut map) = INSTANCES.lock() {
|
||||
if let Some(inst) = map.get_mut(&_instance_id) {
|
||||
@ -161,8 +168,12 @@ pub extern "C" fn nyash_plugin_invoke(
|
||||
}
|
||||
Err(_) => return NYB_E_PLUGIN_ERROR,
|
||||
}
|
||||
} else { return NYB_E_PLUGIN_ERROR; }
|
||||
} else { return NYB_E_PLUGIN_ERROR; }
|
||||
} else {
|
||||
return NYB_E_PLUGIN_ERROR;
|
||||
}
|
||||
} else {
|
||||
return NYB_E_PLUGIN_ERROR;
|
||||
}
|
||||
}
|
||||
Err(_) => NYB_E_INVALID_ARGS,
|
||||
}
|
||||
@ -172,18 +183,20 @@ pub extern "C" fn nyash_plugin_invoke(
|
||||
let args = std::slice::from_raw_parts(_args, _args_len);
|
||||
if _args_len > 0 {
|
||||
match tlv_parse_string(args) {
|
||||
Ok(path) => {
|
||||
match open_file("r", &path) {
|
||||
Ok(mut file) => {
|
||||
let mut buf = Vec::new();
|
||||
if let Err(_) = file.read_to_end(&mut buf) { return NYB_E_PLUGIN_ERROR; }
|
||||
let need = 8usize.saturating_add(buf.len());
|
||||
if preflight(_result, _result_len, need) { return NYB_E_SHORT_BUFFER; }
|
||||
return write_tlv_bytes(&buf, _result, _result_len);
|
||||
Ok(path) => match open_file("r", &path) {
|
||||
Ok(mut file) => {
|
||||
let mut buf = Vec::new();
|
||||
if let Err(_) = file.read_to_end(&mut buf) {
|
||||
return NYB_E_PLUGIN_ERROR;
|
||||
}
|
||||
Err(_) => return NYB_E_PLUGIN_ERROR,
|
||||
let need = 8usize.saturating_add(buf.len());
|
||||
if preflight(_result, _result_len, need) {
|
||||
return NYB_E_SHORT_BUFFER;
|
||||
}
|
||||
return write_tlv_bytes(&buf, _result, _result_len);
|
||||
}
|
||||
}
|
||||
Err(_) => return NYB_E_PLUGIN_ERROR,
|
||||
},
|
||||
Err(_) => return NYB_E_INVALID_ARGS,
|
||||
}
|
||||
} else {
|
||||
@ -196,14 +209,22 @@ pub extern "C" fn nyash_plugin_invoke(
|
||||
Ok(n) => {
|
||||
log_info(&format!("READ {} bytes (entire file)", n));
|
||||
let need = 8usize.saturating_add(buf.len());
|
||||
if preflight(_result, _result_len, need) { return NYB_E_SHORT_BUFFER; }
|
||||
if preflight(_result, _result_len, need) {
|
||||
return NYB_E_SHORT_BUFFER;
|
||||
}
|
||||
return write_tlv_bytes(&buf, _result, _result_len);
|
||||
}
|
||||
Err(_) => return NYB_E_PLUGIN_ERROR,
|
||||
}
|
||||
} else { return NYB_E_INVALID_HANDLE; }
|
||||
} else { return NYB_E_PLUGIN_ERROR; }
|
||||
} else { return NYB_E_PLUGIN_ERROR; }
|
||||
} else {
|
||||
return NYB_E_INVALID_HANDLE;
|
||||
}
|
||||
} else {
|
||||
return NYB_E_PLUGIN_ERROR;
|
||||
}
|
||||
} else {
|
||||
return NYB_E_PLUGIN_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
METHOD_WRITE => {
|
||||
@ -211,50 +232,68 @@ pub extern "C" fn nyash_plugin_invoke(
|
||||
let args = std::slice::from_raw_parts(_args, _args_len);
|
||||
match tlv_parse_optional_string_and_bytes(args) {
|
||||
Ok((Some(path), data)) => {
|
||||
if preflight(_result, _result_len, 12) { return NYB_E_SHORT_BUFFER; }
|
||||
if preflight(_result, _result_len, 12) {
|
||||
return NYB_E_SHORT_BUFFER;
|
||||
}
|
||||
match open_file("w", &path) {
|
||||
Ok(mut file) => {
|
||||
if let Err(_) = file.write_all(&data) { return NYB_E_PLUGIN_ERROR; }
|
||||
if let Err(_) = file.flush() { return NYB_E_PLUGIN_ERROR; }
|
||||
if let Err(_) = file.write_all(&data) {
|
||||
return NYB_E_PLUGIN_ERROR;
|
||||
}
|
||||
if let Err(_) = file.flush() {
|
||||
return NYB_E_PLUGIN_ERROR;
|
||||
}
|
||||
return write_tlv_i32(data.len() as i32, _result, _result_len);
|
||||
}
|
||||
Err(_) => return NYB_E_PLUGIN_ERROR,
|
||||
}
|
||||
}
|
||||
Ok((None, data)) => {
|
||||
if preflight(_result, _result_len, 12) { return NYB_E_SHORT_BUFFER; }
|
||||
if preflight(_result, _result_len, 12) {
|
||||
return NYB_E_SHORT_BUFFER;
|
||||
}
|
||||
if let Ok(mut map) = INSTANCES.lock() {
|
||||
if let Some(inst) = map.get_mut(&_instance_id) {
|
||||
if let Some(file) = inst.file.as_mut() {
|
||||
match file.write(&data) {
|
||||
Ok(n) => {
|
||||
if let Err(_) = file.flush() { return NYB_E_PLUGIN_ERROR; }
|
||||
if let Err(_) = file.flush() {
|
||||
return NYB_E_PLUGIN_ERROR;
|
||||
}
|
||||
log_info(&format!("WRITE {} bytes", n));
|
||||
inst.buffer = Some(data.clone());
|
||||
return write_tlv_i32(n as i32, _result, _result_len);
|
||||
}
|
||||
Err(_) => return NYB_E_PLUGIN_ERROR,
|
||||
}
|
||||
} else { return NYB_E_INVALID_HANDLE; }
|
||||
} else { return NYB_E_PLUGIN_ERROR; }
|
||||
} else { return NYB_E_PLUGIN_ERROR; }
|
||||
} else {
|
||||
return NYB_E_INVALID_HANDLE;
|
||||
}
|
||||
} else {
|
||||
return NYB_E_PLUGIN_ERROR;
|
||||
}
|
||||
} else {
|
||||
return NYB_E_PLUGIN_ERROR;
|
||||
}
|
||||
}
|
||||
Err(_) => NYB_E_INVALID_ARGS,
|
||||
}
|
||||
}
|
||||
METHOD_CLOSE => {
|
||||
// Preflight for Void TLV
|
||||
if preflight(_result, _result_len, 8) { return NYB_E_SHORT_BUFFER; }
|
||||
if preflight(_result, _result_len, 8) {
|
||||
return NYB_E_SHORT_BUFFER;
|
||||
}
|
||||
log_info("CLOSE");
|
||||
if let Ok(mut map) = INSTANCES.lock() {
|
||||
if let Some(inst) = map.get_mut(&_instance_id) {
|
||||
inst.file = None;
|
||||
return write_tlv_void(_result, _result_len);
|
||||
} else {
|
||||
return NYB_E_PLUGIN_ERROR;
|
||||
} else {
|
||||
return NYB_E_PLUGIN_ERROR;
|
||||
}
|
||||
} else {
|
||||
return NYB_E_PLUGIN_ERROR;
|
||||
} else {
|
||||
return NYB_E_PLUGIN_ERROR;
|
||||
}
|
||||
}
|
||||
METHOD_COPY_FROM => {
|
||||
@ -262,8 +301,12 @@ pub extern "C" fn nyash_plugin_invoke(
|
||||
let args = std::slice::from_raw_parts(_args, _args_len);
|
||||
match tlv_parse_handle(args) {
|
||||
Ok((type_id, other_id)) => {
|
||||
if type_id != _type_id { return NYB_E_INVALID_TYPE; }
|
||||
if preflight(_result, _result_len, 8) { return NYB_E_SHORT_BUFFER; }
|
||||
if type_id != _type_id {
|
||||
return NYB_E_INVALID_TYPE;
|
||||
}
|
||||
if preflight(_result, _result_len, 8) {
|
||||
return NYB_E_SHORT_BUFFER;
|
||||
}
|
||||
if let Ok(mut map) = INSTANCES.lock() {
|
||||
// 1) まずsrcからデータを取り出す(不変参照のみ)
|
||||
let mut data: Vec<u8> = Vec::new();
|
||||
@ -283,21 +326,31 @@ pub extern "C" fn nyash_plugin_invoke(
|
||||
read_ok = true;
|
||||
}
|
||||
}
|
||||
if !read_ok { return NYB_E_PLUGIN_ERROR; }
|
||||
} else { return NYB_E_INVALID_HANDLE; }
|
||||
if !read_ok {
|
||||
return NYB_E_PLUGIN_ERROR;
|
||||
}
|
||||
} else {
|
||||
return NYB_E_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
// 2) dstへ書き込み(可変参照)
|
||||
if let Some(dst) = map.get_mut(&_instance_id) {
|
||||
if let Some(fdst) = dst.file.as_mut() {
|
||||
let _ = fdst.seek(SeekFrom::Start(0));
|
||||
if fdst.write_all(&data).is_err() { return NYB_E_PLUGIN_ERROR; }
|
||||
if fdst.write_all(&data).is_err() {
|
||||
return NYB_E_PLUGIN_ERROR;
|
||||
}
|
||||
let _ = fdst.set_len(data.len() as u64);
|
||||
let _ = fdst.flush();
|
||||
}
|
||||
dst.buffer = Some(data);
|
||||
return write_tlv_void(_result, _result_len);
|
||||
} else { return NYB_E_INVALID_HANDLE; }
|
||||
} else { return NYB_E_PLUGIN_ERROR; }
|
||||
} else {
|
||||
return NYB_E_INVALID_HANDLE;
|
||||
}
|
||||
} else {
|
||||
return NYB_E_PLUGIN_ERROR;
|
||||
}
|
||||
}
|
||||
Err(_) => NYB_E_INVALID_ARGS,
|
||||
}
|
||||
@ -305,11 +358,22 @@ pub extern "C" fn nyash_plugin_invoke(
|
||||
METHOD_CLONE_SELF => {
|
||||
// Return a new instance (handle) as TLV Handle
|
||||
// Preflight for Handle TLV: header(4) + entry(4) + payload(8)
|
||||
if preflight(_result, _result_len, 16) { return NYB_E_SHORT_BUFFER; }
|
||||
if preflight(_result, _result_len, 16) {
|
||||
return NYB_E_SHORT_BUFFER;
|
||||
}
|
||||
let new_id = INSTANCE_COUNTER.fetch_add(1, Ordering::Relaxed);
|
||||
if let Ok(mut map) = INSTANCES.lock() { map.insert(new_id, FileBoxInstance { file: None, path: String::new(), buffer: None }); }
|
||||
if let Ok(mut map) = INSTANCES.lock() {
|
||||
map.insert(
|
||||
new_id,
|
||||
FileBoxInstance {
|
||||
file: None,
|
||||
path: String::new(),
|
||||
buffer: None,
|
||||
},
|
||||
);
|
||||
}
|
||||
// Build TLV result
|
||||
let mut payload = [0u8;8];
|
||||
let mut payload = [0u8; 8];
|
||||
payload[0..4].copy_from_slice(&_type_id.to_le_bytes());
|
||||
payload[4..8].copy_from_slice(&new_id.to_le_bytes());
|
||||
return write_tlv_result(&[(8u8, &payload)], _result, _result_len);
|
||||
@ -320,13 +384,15 @@ pub extern "C" fn nyash_plugin_invoke(
|
||||
match tlv_parse_string(args) {
|
||||
Ok(path) => {
|
||||
let exists = std::path::Path::new(&path).exists();
|
||||
if preflight(_result, _result_len, 9) { return NYB_E_SHORT_BUFFER; }
|
||||
if preflight(_result, _result_len, 9) {
|
||||
return NYB_E_SHORT_BUFFER;
|
||||
}
|
||||
return write_tlv_bool(exists, _result, _result_len);
|
||||
}
|
||||
Err(_) => NYB_E_INVALID_ARGS,
|
||||
}
|
||||
}
|
||||
_ => NYB_SUCCESS
|
||||
_ => NYB_SUCCESS,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -337,16 +403,27 @@ fn open_file(mode: &str, path: &str) -> Result<std::fs::File, std::io::Error> {
|
||||
use std::fs::OpenOptions;
|
||||
match mode {
|
||||
"r" => OpenOptions::new().read(true).open(path),
|
||||
"w" => OpenOptions::new().write(true).create(true).truncate(true).open(path),
|
||||
"w" => OpenOptions::new()
|
||||
.write(true)
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.open(path),
|
||||
"a" => OpenOptions::new().append(true).create(true).open(path),
|
||||
"rw" | "r+" => OpenOptions::new().read(true).write(true).create(true).open(path),
|
||||
"rw" | "r+" => OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.create(true)
|
||||
.open(path),
|
||||
_ => OpenOptions::new().read(true).open(path),
|
||||
}
|
||||
}
|
||||
|
||||
fn write_tlv_result(payloads: &[(u8, &[u8])], result: *mut u8, result_len: *mut usize) -> i32 {
|
||||
if result_len.is_null() { return NYB_E_INVALID_ARGS; }
|
||||
let mut buf: Vec<u8> = Vec::with_capacity(4 + payloads.iter().map(|(_,p)| 4 + p.len()).sum::<usize>());
|
||||
if result_len.is_null() {
|
||||
return NYB_E_INVALID_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()); // version
|
||||
buf.extend_from_slice(&(payloads.len() as u16).to_le_bytes()); // argc
|
||||
for (tag, payload) in payloads {
|
||||
@ -380,13 +457,15 @@ fn write_tlv_i32(v: i32, result: *mut u8, result_len: *mut usize) -> i32 {
|
||||
}
|
||||
|
||||
fn write_tlv_bool(v: bool, result: *mut u8, result_len: *mut usize) -> i32 {
|
||||
let b = [if v {1u8} else {0u8}];
|
||||
let b = [if v { 1u8 } else { 0u8 }];
|
||||
write_tlv_result(&[(1u8, &b)], result, result_len)
|
||||
}
|
||||
|
||||
fn preflight(result: *mut u8, result_len: *mut usize, needed: usize) -> bool {
|
||||
unsafe {
|
||||
if result_len.is_null() { return false; }
|
||||
if result_len.is_null() {
|
||||
return false;
|
||||
}
|
||||
if result.is_null() || *result_len < needed {
|
||||
*result_len = needed;
|
||||
return true;
|
||||
@ -395,58 +474,90 @@ fn preflight(result: *mut u8, result_len: *mut usize, needed: usize) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn tlv_parse_header(data: &[u8]) -> Result<(u16,u16,usize), ()> {
|
||||
if data.len() < 4 { return Err(()); }
|
||||
fn tlv_parse_header(data: &[u8]) -> Result<(u16, u16, usize), ()> {
|
||||
if data.len() < 4 {
|
||||
return Err(());
|
||||
}
|
||||
let ver = u16::from_le_bytes([data[0], data[1]]);
|
||||
let argc = u16::from_le_bytes([data[2], data[3]]);
|
||||
if ver != 1 { return Err(()); }
|
||||
if ver != 1 {
|
||||
return Err(());
|
||||
}
|
||||
Ok((ver, argc, 4))
|
||||
}
|
||||
|
||||
fn tlv_parse_two_strings(data: &[u8]) -> Result<(String, String), ()> {
|
||||
let (_, argc, mut pos) = tlv_parse_header(data)?;
|
||||
if argc < 2 { return Err(()); }
|
||||
if argc < 2 {
|
||||
return Err(());
|
||||
}
|
||||
let s1 = tlv_parse_string_at(data, &mut pos)?;
|
||||
let s2 = tlv_parse_string_at(data, &mut pos)?;
|
||||
Ok((s1, s2))
|
||||
}
|
||||
|
||||
fn tlv_parse_string_at(data: &[u8], pos: &mut usize) -> Result<String, ()> {
|
||||
if *pos + 4 > data.len() { return Err(()); }
|
||||
let tag = data[*pos]; let _res = data[*pos+1];
|
||||
let size = u16::from_le_bytes([data[*pos+2], data[*pos+3]]) as usize;
|
||||
if *pos + 4 > data.len() {
|
||||
return Err(());
|
||||
}
|
||||
let tag = data[*pos];
|
||||
let _res = data[*pos + 1];
|
||||
let size = u16::from_le_bytes([data[*pos + 2], data[*pos + 3]]) as usize;
|
||||
*pos += 4;
|
||||
if tag != 6 || *pos + size > data.len() { return Err(()); }
|
||||
let slice = &data[*pos..*pos+size];
|
||||
if tag != 6 || *pos + size > data.len() {
|
||||
return Err(());
|
||||
}
|
||||
let slice = &data[*pos..*pos + size];
|
||||
*pos += size;
|
||||
std::str::from_utf8(slice).map(|s| s.to_string()).map_err(|_| ())
|
||||
std::str::from_utf8(slice)
|
||||
.map(|s| s.to_string())
|
||||
.map_err(|_| ())
|
||||
}
|
||||
|
||||
fn tlv_parse_i32(data: &[u8]) -> Result<i32, ()> {
|
||||
let (_, argc, mut pos) = tlv_parse_header(data)?;
|
||||
if argc < 1 { return Err(()); }
|
||||
if pos + 8 > data.len() { return Err(()); }
|
||||
let tag = data[pos]; let _res = data[pos+1];
|
||||
let size = u16::from_le_bytes([data[pos+2], data[pos+3]]) as usize; pos += 4;
|
||||
if tag != 2 || size != 4 || pos + size > data.len() { return Err(()); }
|
||||
let mut b = [0u8;4]; b.copy_from_slice(&data[pos..pos+4]);
|
||||
if argc < 1 {
|
||||
return Err(());
|
||||
}
|
||||
if pos + 8 > data.len() {
|
||||
return Err(());
|
||||
}
|
||||
let tag = data[pos];
|
||||
let _res = data[pos + 1];
|
||||
let size = u16::from_le_bytes([data[pos + 2], data[pos + 3]]) as usize;
|
||||
pos += 4;
|
||||
if tag != 2 || size != 4 || pos + size > data.len() {
|
||||
return Err(());
|
||||
}
|
||||
let mut b = [0u8; 4];
|
||||
b.copy_from_slice(&data[pos..pos + 4]);
|
||||
Ok(i32::from_le_bytes(b))
|
||||
}
|
||||
|
||||
fn tlv_parse_bytes(data: &[u8]) -> Result<Vec<u8>, ()> {
|
||||
let (_, argc, mut pos) = tlv_parse_header(data)?;
|
||||
if argc < 1 { return Err(()); }
|
||||
if pos + 4 > data.len() { return Err(()); }
|
||||
let tag = data[pos]; let _res = data[pos+1];
|
||||
let size = u16::from_le_bytes([data[pos+2], data[pos+3]]) as usize; pos += 4;
|
||||
if argc < 1 {
|
||||
return Err(());
|
||||
}
|
||||
if pos + 4 > data.len() {
|
||||
return Err(());
|
||||
}
|
||||
let tag = data[pos];
|
||||
let _res = data[pos + 1];
|
||||
let size = u16::from_le_bytes([data[pos + 2], data[pos + 3]]) as usize;
|
||||
pos += 4;
|
||||
// StringタグもBytesタグも受け付ける(互換性のため)
|
||||
if (tag != 6 && tag != 7) || pos + size > data.len() { return Err(()); }
|
||||
Ok(data[pos..pos+size].to_vec())
|
||||
if (tag != 6 && tag != 7) || pos + size > data.len() {
|
||||
return Err(());
|
||||
}
|
||||
Ok(data[pos..pos + size].to_vec())
|
||||
}
|
||||
|
||||
fn tlv_parse_string(data: &[u8]) -> Result<String, ()> {
|
||||
let (_, argc, mut pos) = tlv_parse_header(data)?;
|
||||
if argc < 1 { return Err(()); }
|
||||
if argc < 1 {
|
||||
return Err(());
|
||||
}
|
||||
tlv_parse_string_at(data, &mut pos)
|
||||
}
|
||||
|
||||
@ -454,18 +565,30 @@ fn tlv_parse_optional_string_and_bytes(data: &[u8]) -> Result<(Option<String>, V
|
||||
let (_, argc, mut pos) = tlv_parse_header(data)?;
|
||||
if argc == 1 {
|
||||
// only bytes
|
||||
if pos + 4 > data.len() { return Err(()); }
|
||||
let tag = data[pos]; let _res = data[pos+1];
|
||||
let size = u16::from_le_bytes([data[pos+2], data[pos+3]]) as usize; pos += 4;
|
||||
if (tag != 6 && tag != 7) || pos + size > data.len() { return Err(()); }
|
||||
return Ok((None, data[pos..pos+size].to_vec()));
|
||||
if pos + 4 > data.len() {
|
||||
return Err(());
|
||||
}
|
||||
let tag = data[pos];
|
||||
let _res = data[pos + 1];
|
||||
let size = u16::from_le_bytes([data[pos + 2], data[pos + 3]]) as usize;
|
||||
pos += 4;
|
||||
if (tag != 6 && tag != 7) || pos + size > data.len() {
|
||||
return Err(());
|
||||
}
|
||||
return Ok((None, data[pos..pos + size].to_vec()));
|
||||
} else if argc >= 2 {
|
||||
let s = tlv_parse_string_at(data, &mut pos)?;
|
||||
if pos + 4 > data.len() { return Err(()); }
|
||||
let tag = data[pos]; let _res = data[pos+1];
|
||||
let size = u16::from_le_bytes([data[pos+2], data[pos+3]]) as usize; pos += 4;
|
||||
if (tag != 6 && tag != 7) || pos + size > data.len() { return Err(()); }
|
||||
Ok((Some(s), data[pos..pos+size].to_vec()))
|
||||
if pos + 4 > data.len() {
|
||||
return Err(());
|
||||
}
|
||||
let tag = data[pos];
|
||||
let _res = data[pos + 1];
|
||||
let size = u16::from_le_bytes([data[pos + 2], data[pos + 3]]) as usize;
|
||||
pos += 4;
|
||||
if (tag != 6 && tag != 7) || pos + size > data.len() {
|
||||
return Err(());
|
||||
}
|
||||
Ok((Some(s), data[pos..pos + size].to_vec()))
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
@ -473,13 +596,23 @@ fn tlv_parse_optional_string_and_bytes(data: &[u8]) -> Result<(Option<String>, V
|
||||
|
||||
fn tlv_parse_handle(data: &[u8]) -> Result<(u32, u32), ()> {
|
||||
let (_, argc, mut pos) = tlv_parse_header(data)?;
|
||||
if argc < 1 { return Err(()); }
|
||||
if pos + 4 > data.len() { return Err(()); }
|
||||
let tag = data[pos]; let _res = data[pos+1];
|
||||
let size = u16::from_le_bytes([data[pos+2], data[pos+3]]) as usize; pos += 4;
|
||||
if tag != 8 || size != 8 || pos + size > data.len() { return Err(()); }
|
||||
let mut t = [0u8;4]; t.copy_from_slice(&data[pos..pos+4]);
|
||||
let mut i = [0u8;4]; i.copy_from_slice(&data[pos+4..pos+8]);
|
||||
if argc < 1 {
|
||||
return Err(());
|
||||
}
|
||||
if pos + 4 > data.len() {
|
||||
return Err(());
|
||||
}
|
||||
let tag = data[pos];
|
||||
let _res = data[pos + 1];
|
||||
let size = u16::from_le_bytes([data[pos + 2], data[pos + 3]]) as usize;
|
||||
pos += 4;
|
||||
if tag != 8 || size != 8 || pos + size > data.len() {
|
||||
return Err(());
|
||||
}
|
||||
let mut t = [0u8; 4];
|
||||
t.copy_from_slice(&data[pos..pos + 4]);
|
||||
let mut i = [0u8; 4];
|
||||
i.copy_from_slice(&data[pos + 4..pos + 8]);
|
||||
Ok((u32::from_le_bytes(t), u32::from_le_bytes(i)))
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user