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
34 changes: 23 additions & 11 deletions layout/src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,7 @@ extern "C" {
out: *mut *mut u8,
out_len: *mut u32,
) -> c_int;
fn kvspaceNewChar(
kind: *const c_char,
s: *const c_char,
out: *mut *mut u8,
out_len: *mut u32,
) -> c_int;
fn kvspaceNewCharByte(bytes: *const u8, len: u32, out: *mut *mut u8, out_len: *mut u32)
-> c_int;
fn kvspaceNewChar(bytes: *const u8, len: u32, out: *mut *mut u8, out_len: *mut u32) -> c_int;
fn kvspaceNewBool(v: u8, out: *mut *mut u8, out_len: *mut u32) -> c_int;
fn kvspaceNewInt64(v: i64, out: *mut *mut u8, out_len: *mut u32) -> c_int;
fn kvspaceNewFloat64(v: f64, out: *mut *mut u8, out_len: *mut u32) -> c_int;
Expand Down Expand Up @@ -307,16 +300,35 @@ pub fn new_ptr(kind: &str, target: &str, array_len: i32) -> Vec<u8> {
}

pub fn new_char(kind: &str, s: &str) -> Vec<u8> {
let bytes = s.as_bytes();
if kind == "char/utf8" {
return new_char_byte(bytes);
}
let (raw, n) = if kind == "char/utf32" {
let v: Vec<u8> = s.chars().flat_map(|c| (c as u32).to_le_bytes()).collect();
let n = (v.len() / 4) as i32;
(v, n)
} else {
(bytes.to_vec(), bytes.len() as i32)
};
let ck = CString::new(kind).expect("no NUL");
let cs = CString::new(s).expect("no NUL");
let dims = [n];
call_alloc(|out, out_len| unsafe {
kvspaceNewChar(ck.as_ptr(), cs.as_ptr(), out, out_len)
kvspaceTlvEncode(
ck.as_ptr(),
raw.as_ptr(),
raw.len() as u32,
dims.as_ptr(),
1,
out,
out_len,
)
})
}

pub fn new_char_byte(bytes: &[u8]) -> Vec<u8> {
call_alloc(|out, out_len| unsafe {
kvspaceNewCharByte(bytes.as_ptr(), bytes.len() as u32, out, out_len)
kvspaceNewChar(bytes.as_ptr(), bytes.len() as u32, out, out_len)
})
}

Expand Down
2 changes: 1 addition & 1 deletion runtime-rwirext_example/go/json/edge_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ func TestEdgeKeys(t *testing.T) {
c := rtConn(t)
defer disconnect(c)
cases := []string{
`{"a.b":1}`, // 点号 key(应拒绝
`{"a.b":1}`, // 点号 key(合法,· 才是成员分隔符
`{"a/b":1}`, // 斜杠 key(应拒绝)
`{"a[b]":1}`, // 方括号 key(应拒绝)
`{"a\nb":1}`, // 换行 key(应拒绝)
Expand Down
35 changes: 22 additions & 13 deletions runtime-rwirext_example/go/json/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ extern int kvspaceSet(void *h, const char *const *keys, const uint8_t *vals,
extern int kvspaceList(void *h, const char *prefix, int expand_ext, int resolve,
uint8_t **out, uint32_t *out_len);
extern int kvspaceDel(void *h, const char *const *keys, uint32_t nkeys, char *err, uint32_t err_cap);
extern int kvspaceDelTree(void *h, const char *prefix, char *err, uint32_t err_cap);
extern int kvspaceMkindex(void *h, const char *path, char *err, uint32_t err_cap);
extern int kvspaceNewChar(const char *kind, const char *s, uint8_t **out, uint32_t *out_len);
extern int kvspaceNewChar(const uint8_t *bytes, uint32_t len, uint8_t **out, uint32_t *out_len);

// XValue 头(repr(C),对齐 kvspace ABI):kindexpr 为唯一类型真相,body 段靠 offset/len 定位。
typedef struct {
Expand Down Expand Up @@ -124,13 +125,11 @@ func setTLV(c unsafe.Pointer, key string, tlv []byte) {
}

func setChar(c unsafe.Pointer, key, val string) {
ck := cstr("char/utf8")
cv := cstr(val)
defer C.free(unsafe.Pointer(ck))
defer C.free(unsafe.Pointer(cv))
cv := C.CBytes([]byte(val))
defer C.free(cv)
var out *C.uint8_t
var outLen C.uint32_t
if C.kvspaceNewChar(ck, cv, &out, &outLen) != 0 || out == nil {
if C.kvspaceNewChar((*C.uint8_t)(cv), C.uint32_t(len(val)), &out, &outLen) != 0 || out == nil {
return
}
defer C.kvspaceBytesFree(out, outLen)
Expand All @@ -150,6 +149,13 @@ func del(c unsafe.Pointer, key string) {
C.kvspaceDel(c, &keys[0], 1, &err[0], 256)
}

func delTree(c unsafe.Pointer, prefix string) {
cp := cstr(prefix)
defer C.free(unsafe.Pointer(cp))
var err [256]C.char
C.kvspaceDelTree(c, cp, &err[0], 256)
}

func mkindex(c unsafe.Pointer, path string) {
cp := cstr(path)
defer C.free(unsafe.Pointer(cp))
Expand Down Expand Up @@ -216,16 +222,15 @@ func parseTLV(data []byte) (kind string, raw []byte, arrLen int) {
return kind, raw, arrLen
}

// constructTLV:char/* 走 kvspaceNewChar,数值/布尔走 kvspaceTlvEncode(arrLen>1 → 一维 [arrLen])。
// constructTLV:char/utf8 走 kvspaceNewChar(显式长度,NUL 安全),
// 其余(数值/布尔/objindex 等)走 kvspaceTlvEncode(arrLen>1 → 一维 [arrLen])。
func constructTLV(kind string, raw []byte, arrLen int) []byte {
if strings.HasPrefix(kind, "char/") {
ck := cstr(kind)
cv := C.CBytes(append(append([]byte{}, raw...), 0)) // NUL 结尾
defer C.free(unsafe.Pointer(ck))
defer C.free(cv)
if kind == "char/utf8" {
buf := C.CBytes(raw)
defer C.free(buf)
var out *C.uint8_t
var ol C.uint32_t
if C.kvspaceNewChar(ck, (*C.char)(cv), &out, &ol) != 0 || out == nil {
if C.kvspaceNewChar((*C.uint8_t)(buf), C.uint32_t(len(raw)), &out, &ol) != 0 || out == nil {
return nil
}
defer C.kvspaceBytesFree(out, ol)
Expand Down Expand Up @@ -519,6 +524,10 @@ func readArr(c unsafe.Pointer, path string) []interface{} {
}

func writeMap(c unsafe.Pointer, root string, m map[string]any) error {
// 覆盖语义:root 子树等于 src,写前清空旧子树(杜绝孤儿键与 obj→scalar 脏读)。
if root != "" && root != "/" {
delTree(c, root)
}
return writeObj(c, root, m)
}

Expand Down
5 changes: 3 additions & 2 deletions runtime-rwirext_example/py/numpy/numpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def _bind():
_ks.kvspaceList.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_int, ctypes.c_int,
ctypes.POINTER(ctypes.POINTER(ctypes.c_uint8)), ctypes.POINTER(ctypes.c_uint32)]
_ks.kvspaceList.restype = ctypes.c_int
_ks.kvspaceNewChar.argtypes = [ctypes.c_char_p, ctypes.c_char_p,
_ks.kvspaceNewChar.argtypes = [ctypes.POINTER(ctypes.c_uint8), ctypes.c_uint32,
ctypes.POINTER(ctypes.POINTER(ctypes.c_uint8)), ctypes.POINTER(ctypes.c_uint32)]
_ks.kvspaceNewChar.restype = ctypes.c_int
_ks.kvspaceDel.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_char_p), ctypes.c_uint32,
Expand Down Expand Up @@ -211,7 +211,8 @@ def kv_get(self, key):

def kv_set(self, key, val):
out = ctypes.POINTER(ctypes.c_uint8)(); ol = ctypes.c_uint32()
if _ks.kvspaceNewChar(b"char/utf8", val.encode(), ctypes.byref(out), ctypes.byref(ol)) != 0:
b = val.encode()
if _ks.kvspaceNewChar(b, len(b), ctypes.byref(out), ctypes.byref(ol)) != 0:
return
_ks.kvspaceShmSet(self.kv, key.encode(), out, ol.value)
_ks.kvspaceBytesFree(out, ol.value)
Expand Down
5 changes: 3 additions & 2 deletions runtime-rwirext_example/rust/term/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ unsafe extern "C" {
err: *mut c_char,
err_cap: u32,
) -> c_int;
fn kvspaceNewChar(kind: *const c_char, s: *const c_char, out: *mut *mut u8, out_len: *mut u32) -> c_int;
fn kvspaceNewChar(bytes: *const u8, len: u32, out: *mut *mut u8, out_len: *mut u32) -> c_int;
fn kvspaceDecodeHead(data: *const u8, data_len: u32, out: *mut kvspaceHead_t) -> c_int;

// rwirext ABI(kvspace 不提供的 runtime 语义;句柄传扩展自连的 kvspace)
Expand Down Expand Up @@ -163,7 +163,8 @@ fn kv_get(kv: *mut c_void, key: &str) -> String {
fn kv_set(kv: *mut c_void, key: &str, val: &str) {
let mut out: *mut u8 = null_mut();
let mut out_len: u32 = 0;
if unsafe { kvspaceNewChar(cs("char/utf8").as_ptr(), cs(val).as_ptr(), &mut out, &mut out_len) } != 0
let vb = cs(val);
if unsafe { kvspaceNewChar(vb.as_ptr() as *const u8, vb.as_bytes().len() as u32, &mut out, &mut out_len) } != 0
|| out.is_null()
{
return;
Expand Down
3 changes: 1 addition & 2 deletions runtime/src/runtime_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,7 @@ extern int kvspaceTlvEncodePtr(const char *kind, const uint8_t *raw, uint32_t
extern int kvspaceDecodeHead(const uint8_t *data, uint32_t data_len, kvspaceHead_t *out);
extern int kvspaceNewPtr(const char *kind, const char *target, int32_t array_len,
uint8_t **out, uint32_t *out_len);
extern int kvspaceNewChar(const char *kind, const char *s, uint8_t **out, uint32_t *out_len);
extern int kvspaceNewCharByte(const uint8_t *bytes, uint32_t len, uint8_t **out, uint32_t *out_len);
extern int kvspaceNewChar(const uint8_t *bytes, uint32_t len, uint8_t **out, uint32_t *out_len);
extern int kvspaceNewBool(uint8_t v, uint8_t **out, uint32_t *out_len);
extern int kvspaceNewInt64(int64_t v, uint8_t **out, uint32_t *out_len);
extern int kvspaceNewFloat64(double v, uint8_t **out, uint32_t *out_len);
Expand Down
Loading