Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion layout/src/code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//!
//! 存储约定:
//! /lib/<pkg>·<name>/[0,0] 布局后签名(kind=rwfunc)
//! /lib/<pkg>·<name>/<param> 命名参数→slot 指针(kind=char, isptr=1)
//! /lib/<pkg>·<name>/<param> 命名参数→slot 指针(langtype=char, ref=1)
//! /lib/<pkg>·<name>/[i,j] 编译后指令(kind=rwir),i 从 1 开始
//! /lib/<pkg>·<name>/‥labels/<l> label → irseq
//! /lib/<pkg>·<name>.src 源码副本
Expand Down
47 changes: 29 additions & 18 deletions layout/src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,15 @@ extern "C" {
err: *mut c_char,
err_cap: u32,
) -> c_int;
/// 新位置写:按 (xkind, kindexpr, body_len) 分配新 box、写 head,返回 body 偏移指针。
/// 新位置写:按 (ref, storetype, ro, vid, langtype, body_len) 分配新 box、写 head,返回 body 偏移指针。
fn kvspaceWriteNewPlace(
h: Handle,
key: *const c_char,
xkind: u8,
kindexpr: *const c_char,
r#ref: u8,
storetype: u8,
ro: u8,
vid: u32,
langtype: *const c_char,
body_len: u32,
body: *mut *mut u8,
err: *mut c_char,
Expand Down Expand Up @@ -116,17 +119,20 @@ extern "C" {
fn kvspaceNewFloat64(v: f64, out: *mut *mut u8, out_len: *mut u32) -> c_int;
}

/// XValueHead 解码结果(与 kvspace-durable 的 kvspaceHead_t 布局一致)。kindexpr 为唯一类型真相。
/// XValueHead 解码结果(与 kvspace/include/kvspace/kvspace.h 的 kvspaceHead_t 逐字段对齐)。
/// 三正交轴 ref×storetype×langtype;langtype 为语义类型真相(含 [dims]、无 ptr/ext 前缀)。
#[repr(C)]
pub struct kvspaceHead_t {
pub xkind: u8,
pub kindexpr: [u8; 256],
pub kind_off: i32,
pub ndim: i32,
pub dims: [i32; 8],
pub headlen: u16,
pub r#ref: u8,
pub storetype: u8,
pub ro: u8,
pub vid: u32,
pub body_len: i32,
pub ndim: i32,
pub dims: [i32; 8],
pub langtype: [u8; 256],
pub langtype_len: i32,
pub body_offset: i32,
}

Expand Down Expand Up @@ -195,8 +201,8 @@ impl Kv {

fn write_new_place(&mut self, key: &str, tlv: &[u8]) -> Result<(), String> {
let h = decode_head(tlv);
let klen = h.kindexpr.iter().position(|&b| b == 0).unwrap_or(0);
let kindexpr = CString::new(&h.kindexpr[..klen]).expect("no NUL in kindexpr");
let llen = h.langtype.iter().position(|&b| b == 0).unwrap_or(0);
let langtype = CString::new(&h.langtype[..llen]).expect("no NUL in langtype");
let ck = CString::new(key).expect("no NUL in key");
let body_off = h.body_offset as usize;
let body_len = h.body_len.max(0) as usize;
Expand All @@ -206,8 +212,11 @@ impl Kv {
kvspaceWriteNewPlace(
self.h,
ck.as_ptr(),
h.xkind,
kindexpr.as_ptr(),
h.r#ref,
h.storetype,
h.ro,
h.vid,
langtype.as_ptr(),
body_len as u32,
&mut body,
err.as_mut_ptr(),
Expand Down Expand Up @@ -350,14 +359,16 @@ pub fn tlv_encode(kind: &str, raw: &[u8], array_len: i32) -> Vec<u8> {
/// 解码 XValueHead。
pub fn decode_head(data: &[u8]) -> kvspaceHead_t {
let mut h = kvspaceHead_t {
xkind: 0,
kindexpr: [0u8; 256],
kind_off: 0,
ndim: 0,
dims: [0i32; 8],
headlen: 0,
r#ref: 0,
storetype: 0,
ro: 0,
vid: 0,
body_len: 0,
ndim: 0,
dims: [0i32; 8],
langtype: [0u8; 256],
langtype_len: 0,
body_offset: 0,
};
unsafe {
Expand Down
12 changes: 6 additions & 6 deletions layout/src/kvkind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ pub fn head(data: &[u8]) -> ffi::kvspaceHead_t {
ffi::decode_head(data)
}

/// 解析 kindexpr 内容 → (dims, base kind)。kindexpr 无前缀(ref/ptr 归 head.xkind)。
/// 解析 kindexpr 内容 → (dims, base kind)。kindexpr 无前缀(ref/ptr 归 head.ref)。
pub fn parse_kindexpr(kx: &str) -> (Vec<i32>, String) {
if kx.starts_with('[') {
match kx.find(']') {
Expand All @@ -64,11 +64,11 @@ pub fn kindexpr(data: &[u8]) -> String {
}
let h = ffi::decode_head(data);
let end = h
.kindexpr
.langtype
.iter()
.position(|&b| b == 0)
.unwrap_or(h.kindexpr.len());
String::from_utf8_lossy(&h.kindexpr[..end]).into_owned()
.unwrap_or(h.langtype.len());
String::from_utf8_lossy(&h.langtype[..end]).into_owned()
}

pub fn kind(data: &[u8]) -> String {
Expand All @@ -79,7 +79,7 @@ pub fn kind(data: &[u8]) -> String {
}

pub fn is_ptr(data: &[u8]) -> bool {
!data.is_empty() && ffi::decode_head(data).xkind == 1
!data.is_empty() && ffi::decode_head(data).r#ref == 1
}

pub fn array_len(data: &[u8]) -> i32 {
Expand Down Expand Up @@ -128,7 +128,7 @@ pub fn display(data: &[u8]) -> String {
}
let h = ffi::decode_head(data);
let b = body(data, &h);
if h.xkind == 1 {
if h.r#ref == 1 {
return format!("→{}:{}", String::from_utf8_lossy(b), k);
}
format!("{}:{}", k, plain_value(&k, b))
Expand Down
79 changes: 71 additions & 8 deletions runtime-rs/src/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,40 @@ use std::ptr::null_mut;
use crate::ffi::*;
use crate::rwir;

const KVSPACE_REF_EXT: u8 = 2;
const STORETYPE_ATOM: u8 = 1;
const STORETYPE_ARRAYND: u8 = 2;
const STORETYPE_INDEX: u8 = 3;
const STORETYPE_EXTINDEX: u8 = 4;

/// 由完整 langtype kindexpr 串推 storetype(镜像 kvspace-durable::storetype_from_kindexpr):
/// extindex / index(含 rwfunc/defrwir) / 对象(·)·路径(/) → INDEX 系;带 [dims] → ARRAYND;否则 ATOM。
fn storetype_from_kindexpr(kx: &str) -> u8 {
if kx.is_empty() {
return 0;
}
let (has_dims, base) = match kx.strip_prefix('[') {
Some(_) => match kx.find(']') {
Some(e) => (true, &kx[e + 1..]),
None => (false, kx),
},
None => (false, kx),
};
if base == "extindex" {
return STORETYPE_EXTINDEX;
}
if matches!(base, "index" | "rwfunc" | "defrwir")
|| base.starts_with('/')
|| base.contains('\u{b7}')
{
return STORETYPE_INDEX;
}
if has_dims {
return STORETYPE_ARRAYND;
}
STORETYPE_ATOM
}

pub struct Engine {
pub rt: *mut c_void, // kvlang runtime 句柄
pub kv: *mut c_void, // kvspace 句柄(自持,同时传给 rwirext)
Expand All @@ -17,10 +51,19 @@ pub struct Engine {

impl Engine {
// ── kvspace 读写(绝对路径,char/utf8 与 char/utf32 编解码)─────────
/// 写即构造:按 (kindexpr, body) 向 kvspace 要偏移指针后直接写 body 字节——
/// 写即构造:按三正交轴 (ref, storetype, ro, vid, langtype) + body 向 kvspace 要偏移指针后直接写 body 字节——
/// key 已存在且同 body_len → WriteInPlace(原 box 就地);否则 WriteNewPlace(新 box)。
/// 两分支各调唯一原语、无预 encode 整条 TLV、无中转 buffer、无 free。
fn write_construct(&self, key: &str, xkind: u8, kindexpr: &str, body: &[u8]) {
fn write_construct(
&self,
key: &str,
r#ref: u8,
storetype: u8,
ro: u8,
vid: u32,
langtype: &str,
body: &[u8],
) {
unsafe {
let ck = cs(key);
let mut bp: *mut u8 = null_mut();
Expand All @@ -38,8 +81,11 @@ impl Engine {
kvspaceWriteNewPlace(
self.kv,
ck.as_ptr(),
xkind,
cs(kindexpr).as_ptr(),
r#ref,
storetype,
ro,
vid,
cs(langtype).as_ptr(),
body.len() as u32,
&mut bp,
err.as_mut_ptr() as *mut c_char,
Expand Down Expand Up @@ -91,7 +137,16 @@ impl Engine {
/// 扩展世界(@ ref=2)句柄编码写入:kind=目标完整 kindexpr(如 "[]uint8"),body=定位串。
/// 读取该 key 时由 read_at 按 body 前缀路由给对应 /lib/networld/* 兑现器还原真实字节。
pub fn set_ext_handle(&self, key: &str, target_kindexpr: &str, locator: &str) {
self.write_construct(key, 2, target_kindexpr, locator.as_bytes());
let st = storetype_from_kindexpr(target_kindexpr);
self.write_construct(
key,
KVSPACE_REF_EXT,
st,
0,
0,
target_kindexpr,
locator.as_bytes(),
);
}

/// 读 key 的 head,返回 (ref, body 串)。仅 ref==2 时 body 有意义(扩展句柄定位串)。
Expand All @@ -103,7 +158,7 @@ impl Engine {
unsafe {
let mut head = KvspaceHead::default();
kvspaceDecodeHead(tlv.as_ptr(), tlv.len() as u32, &mut head);
let r = match head.xkind {
let r = match head.r#ref {
2 => 2,
1 => 1,
_ => 0,
Expand Down Expand Up @@ -173,7 +228,7 @@ impl Engine {
if kvspaceDecodeHead(tlv.as_ptr(), tlv.len() as u32, &mut h) != 0 {
return Vec::new();
}
let r = match h.xkind {
let r = match h.r#ref {
2 => 2,
1 => 1,
_ => 0,
Expand Down Expand Up @@ -292,7 +347,15 @@ impl Engine {
.trim_end_matches('\0')
.to_string();
let (bo, bl) = (head.body_offset as usize, head.body_len.max(0) as usize);
self.write_construct(key, head.xkind, &kx, &tlv[bo..bo + bl]);
self.write_construct(
key,
head.r#ref,
head.storetype,
head.ro,
head.vid,
&kx,
&tlv[bo..bo + bl],
);
}
}

Expand Down
36 changes: 22 additions & 14 deletions runtime-rs/src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,36 @@

use std::ffi::{c_char, c_int, c_void, CStr, CString};

/// kvspaceDecodeHead 输出(与 kvspace-durable/src/ffi.rs::kvspaceHead_t 对齐)。kindexpr 为唯一类型真相。
/// kvspaceDecodeHead 输出(逐字段对齐 kvspace/include/kvspace/kvspace.h 的 kvspaceHead_t)。
/// 三正交轴 ref×storetype×langtype;kindexpr 即该 ABI 的 langtype 槽(本 runtime 内部沿用 kindexpr 命名)。
#[repr(C)]
pub struct KvspaceHead {
pub xkind: u8,
pub kindexpr: [u8; 256],
pub kind_off: i32,
pub ndim: i32,
pub dims: [i32; 8],
pub headlen: u16,
pub r#ref: u8,
pub storetype: u8,
pub ro: u8,
pub vid: u32,
pub body_len: i32,
pub ndim: i32,
pub dims: [i32; 8],
pub kindexpr: [u8; 256],
pub kindexpr_len: i32,
pub body_offset: i32,
}

impl Default for KvspaceHead {
fn default() -> Self {
KvspaceHead {
xkind: 0,
kindexpr: [0u8; 256],
kind_off: 0,
ndim: 0,
dims: [0i32; 8],
headlen: 0,
r#ref: 0,
storetype: 0,
ro: 0,
vid: 0,
body_len: 0,
ndim: 0,
dims: [0i32; 8],
kindexpr: [0u8; 256],
kindexpr_len: 0,
body_offset: 0,
}
}
Expand Down Expand Up @@ -99,12 +104,15 @@ unsafe extern "C" {
err: *mut c_char,
err_cap: u32,
) -> c_int;
/// 新位置写:按 (kindexpr, body_len) 分配新 box、写 head,返回 body 偏移指针。
/// 新位置写:按 (ref, storetype, ro, vid, langtype, body_len) 分配新 box、写 head,返回 body 偏移指针。
pub fn kvspaceWriteNewPlace(
h: *mut c_void,
key: *const c_char,
xkind: u8,
kindexpr: *const c_char,
r#ref: u8,
storetype: u8,
ro: u8,
vid: u32,
langtype: *const c_char,
body_len: u32,
body: *mut *mut u8,
err: *mut c_char,
Expand Down
Loading
Loading