feat(napi): string latin1 support
This commit is contained in:
parent
dfb7518cac
commit
371cc5eab0
11 changed files with 98 additions and 24 deletions
|
@ -158,7 +158,7 @@ yarn test
|
|||
| [napi_create_bigint_int64](https://nodejs.org/api/n-api.html#n_api_napi_create_bigint_int64) | 6 | v10.7.0 | ✅ |
|
||||
| [napi_create_bigint_uint64](https://nodejs.org/api/n-api.html#n_api_napi_create_bigint_uint64) | 6 | v10.7.0 | ✅ |
|
||||
| [napi_create_bigint_words](https://nodejs.org/api/n-api.html#n_api_napi_create_bigint_words) | 6 | v10.7.0 | ✅ |
|
||||
| [napi_create_string_latin1](https://nodejs.org/api/n-api.html#n_api_napi_create_string_latin1) | 1 | v8.0.0 | ⛔️ |
|
||||
| [napi_create_string_latin1](https://nodejs.org/api/n-api.html#n_api_napi_create_string_latin1) | 1 | v8.0.0 | ✅ |
|
||||
| [napi_create_string_utf16](https://nodejs.org/api/n-api.html#n_api_napi_create_string_utf16) | 1 | v8.0.0 | ✅ |
|
||||
| [napi_create_string_utf8](https://nodejs.org/api/n-api.html#n_api_napi_create_string_utf8) | 1 | v8.0.0 | ✅ |
|
||||
|
||||
|
@ -181,12 +181,12 @@ yarn test
|
|||
| [napi_get_value_external](https://nodejs.org/api/n-api.html#n_api_napi_get_value_external) | 1 | v8.0.0 | ✅ |
|
||||
| [napi_get_value_int32](https://nodejs.org/api/n-api.html#n_api_napi_get_value_int32) | 1 | v8.0.0 | ✅ |
|
||||
| [napi_get_value_int64](https://nodejs.org/api/n-api.html#n_api_napi_get_value_int64) | 1 | v8.0.0 | ✅ |
|
||||
| [napi_get_value_string_latin1](https://nodejs.org/api/n-api.html#n_api_napi_get_value_string_latin1) | 1 | v8.0.0 | ⛔️ |
|
||||
| [napi_get_value_string_latin1](https://nodejs.org/api/n-api.html#n_api_napi_get_value_string_latin1) | 1 | v8.0.0 | ✅ |
|
||||
| [napi_get_value_string_utf8](https://nodejs.org/api/n-api.html#n_api_napi_get_value_string_utf8) | 1 | v8.0.0 | ✅ |
|
||||
| [napi_get_value_string_utf16](https://nodejs.org/api/n-api.html#n_api_napi_get_value_string_utf16) | 1 | v8.0.0 | ✅ |
|
||||
| [napi_get_value_uint32](https://nodejs.org/api/n-api.html#n_api_napi_get_value_uint32) | 1 | v8.0.0 | ✅ |
|
||||
| [napi_get_boolean](https://nodejs.org/api/n-api.html#n_api_napi_get_boolean) | 1 | v8.0.0 | ✅ |
|
||||
| [napi_get_global](https://nodejs.org/api/n-api.html#n_api_napi_get_global) | 1 | v8.0.0 | ⛔️ |
|
||||
| [napi_get_global](https://nodejs.org/api/n-api.html#n_api_napi_get_global) | 1 | v8.0.0 | ✅ |
|
||||
| [napi_get_null](https://nodejs.org/api/n-api.html#n_api_napi_get_null) | 1 | v8.0.0 | ✅ |
|
||||
| [napi_get_undefined](https://nodejs.org/api/n-api.html#n_api_napi_get_undefined) | 1 | v8.0.0 | ✅ |
|
||||
|
||||
|
|
|
@ -13,10 +13,15 @@ edition = "2018"
|
|||
libuv = ["futures"]
|
||||
tokio_rt = ["futures", "tokio", "once_cell"]
|
||||
serde-json = ["serde", "serde_json"]
|
||||
latin1 = ["encoding_rs"]
|
||||
|
||||
[dependencies]
|
||||
napi-sys = { version = "0.4", path = "../sys" }
|
||||
|
||||
[dependencies.encoding_rs]
|
||||
version = "0.8"
|
||||
optional = true
|
||||
|
||||
[dependencies.futures]
|
||||
version = "0.3"
|
||||
optional = true
|
||||
|
|
|
@ -196,6 +196,20 @@ impl Env {
|
|||
Ok(JsString::from_raw_unchecked(self.0, raw_value))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn create_string_latin1(&self, chars: &[u8]) -> Result<JsString> {
|
||||
let mut raw_value = ptr::null_mut();
|
||||
check_status(unsafe {
|
||||
sys::napi_create_string_latin1(
|
||||
self.0,
|
||||
chars.as_ptr() as *const _,
|
||||
chars.len() as u64,
|
||||
&mut raw_value,
|
||||
)
|
||||
})?;
|
||||
Ok(JsString::from_raw_unchecked(self.0, raw_value))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn create_symbol_from_js_string(&self, description: JsString) -> Result<JsSymbol> {
|
||||
let mut result = ptr::null_mut();
|
||||
|
|
|
@ -4,6 +4,9 @@ use std::ptr;
|
|||
use std::slice;
|
||||
use std::str;
|
||||
|
||||
#[cfg(feature = "latin1")]
|
||||
use encoding_rs;
|
||||
|
||||
use super::Value;
|
||||
use crate::error::check_status;
|
||||
use crate::{sys, Error, Result, Status};
|
||||
|
@ -13,20 +16,29 @@ pub struct JsString(pub(crate) Value);
|
|||
|
||||
impl JsString {
|
||||
#[inline]
|
||||
pub fn len(&self) -> Result<usize> {
|
||||
pub fn utf8_len(&self) -> Result<usize> {
|
||||
let mut length = 0;
|
||||
check_status(unsafe {
|
||||
sys::napi_get_value_string_utf8(self.0.env, self.0.value, ptr::null_mut(), 0, &mut length)
|
||||
})?;
|
||||
Ok(length as usize)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn latin1_len(&self) -> Result<usize> {
|
||||
let mut length = 0;
|
||||
check_status(unsafe {
|
||||
sys::napi_get_value_string_latin1(self.0.env, self.0.value, ptr::null_mut(), 0, &mut length)
|
||||
})?;
|
||||
Ok(length as usize)
|
||||
}
|
||||
}
|
||||
|
||||
impl JsString {
|
||||
#[inline]
|
||||
pub fn get_ref(&self) -> Result<&[u8]> {
|
||||
pub fn get_utf8(&self) -> Result<&[u8]> {
|
||||
let mut written_char_count: u64 = 0;
|
||||
let len = self.len()? + 1;
|
||||
let len = self.utf8_len()? + 1;
|
||||
let mut result = Vec::with_capacity(len);
|
||||
unsafe {
|
||||
check_status(sys::napi_get_value_string_utf8(
|
||||
|
@ -46,9 +58,31 @@ impl JsString {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn chars(&self) -> Result<&[char]> {
|
||||
pub fn get_latin1(&self) -> Result<(&[u8], usize)> {
|
||||
let mut written_char_count: u64 = 0;
|
||||
let len = self.len()? + 1;
|
||||
let len = self.latin1_len()? + 1;
|
||||
let mut result = Vec::with_capacity(len);
|
||||
unsafe {
|
||||
check_status(sys::napi_get_value_string_latin1(
|
||||
self.0.env,
|
||||
self.0.value,
|
||||
result.as_mut_ptr(),
|
||||
len as u64,
|
||||
&mut written_char_count,
|
||||
))?;
|
||||
let ptr = result.as_ptr();
|
||||
mem::forget(result);
|
||||
Ok((
|
||||
slice::from_raw_parts(ptr as *const u8, written_char_count as usize),
|
||||
written_char_count as usize,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_utf8_chars(&self) -> Result<&[char]> {
|
||||
let mut written_char_count: u64 = 0;
|
||||
let len = self.utf8_len()? + 1;
|
||||
let mut result = Vec::with_capacity(len);
|
||||
unsafe {
|
||||
check_status(sys::napi_get_value_string_utf8(
|
||||
|
@ -69,13 +103,21 @@ impl JsString {
|
|||
}
|
||||
|
||||
pub fn as_str(&self) -> Result<&str> {
|
||||
str::from_utf8(self.get_ref()?)
|
||||
str::from_utf8(self.get_utf8()?)
|
||||
.map_err(|e| Error::new(Status::GenericFailure, format!("{:?}", e)))
|
||||
}
|
||||
|
||||
#[cfg(feature = "latin1")]
|
||||
pub fn as_latin1_string(&self) -> Result<String> {
|
||||
let (latin1_bytes, len) = self.get_latin1()?;
|
||||
let mut dst_str = unsafe { String::from_utf8_unchecked(vec![0; len * 2 + 1]) };
|
||||
encoding_rs::mem::convert_latin1_to_str(latin1_bytes, dst_str.as_mut_str());
|
||||
Ok(dst_str)
|
||||
}
|
||||
|
||||
pub fn get_ref_mut(&mut self) -> Result<&mut [u8]> {
|
||||
let mut written_char_count: u64 = 0;
|
||||
let len = self.len()? + 1;
|
||||
let len = self.utf8_len()? + 1;
|
||||
let mut result = Vec::with_capacity(len);
|
||||
unsafe {
|
||||
check_status(sys::napi_get_value_string_utf8(
|
||||
|
@ -100,7 +142,7 @@ impl TryFrom<JsString> for Vec<u16> {
|
|||
type Error = Error;
|
||||
|
||||
fn try_from(value: JsString) -> Result<Vec<u16>> {
|
||||
let mut result = Vec::with_capacity(value.len()? + 1); // Leave room for trailing null byte
|
||||
let mut result = Vec::with_capacity(value.utf8_len()? + 1); // Leave room for trailing null byte
|
||||
|
||||
unsafe {
|
||||
let mut written_char_count = 0;
|
||||
|
|
|
@ -9,7 +9,7 @@ crate-type = ["cdylib"]
|
|||
|
||||
[dependencies]
|
||||
futures = "0.3"
|
||||
napi = { path = "../napi", features = ["libuv", "tokio_rt", "serde-json"] }
|
||||
napi = { path = "../napi", features = ["libuv", "tokio_rt", "serde-json", "latin1"] }
|
||||
napi-derive = { path = "../napi-derive" }
|
||||
serde = "1"
|
||||
serde_bytes = "0.11"
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
# Snapshot report for `test_module/__test__/string.spec.js`
|
||||
|
||||
The actual snapshot is saved in `string.spec.js.snap`.
|
||||
|
||||
Generated by [AVA](https://avajs.dev).
|
||||
|
||||
## should be able to concat string
|
||||
|
||||
> Snapshot 1
|
||||
|
||||
'JavaScript 🌳 你好 napi + Rust 🦀 string!'
|
Binary file not shown.
|
@ -6,3 +6,12 @@ test('should be able to concat string', (t) => {
|
|||
const fixture = 'JavaScript 🌳 你好 napi'
|
||||
t.snapshot(bindings.concatString(fixture))
|
||||
})
|
||||
|
||||
test('should be able to concat latin1 string', (t) => {
|
||||
const fixture = '涽¾DEL'
|
||||
t.snapshot(bindings.concatLatin1String(fixture))
|
||||
})
|
||||
|
||||
test('should be able to crate latin1 string', (t) => {
|
||||
t.snapshot(bindings.createLatin1())
|
||||
})
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -1,13 +1,28 @@
|
|||
use napi::{CallContext, JsString, Module, Result};
|
||||
|
||||
#[js_function(1)]
|
||||
pub fn concat_string(ctx: CallContext) -> Result<JsString> {
|
||||
fn concat_string(ctx: CallContext) -> Result<JsString> {
|
||||
let in_string = ctx.get::<JsString>(0)?;
|
||||
let out_string = format!("{} + Rust 🦀 string!", in_string.as_str()?);
|
||||
ctx.env.create_string_from_std(out_string)
|
||||
}
|
||||
|
||||
#[js_function(1)]
|
||||
fn concat_latin1_string(ctx: CallContext) -> Result<JsString> {
|
||||
let in_string = ctx.get::<JsString>(0)?;
|
||||
let out_string = format!("{} + Rust 🦀 string!", in_string.as_latin1_string()?);
|
||||
ctx.env.create_string_from_std(out_string)
|
||||
}
|
||||
|
||||
#[js_function]
|
||||
fn create_latin1(ctx: CallContext) -> Result<JsString> {
|
||||
let bytes = vec![169, 191];
|
||||
ctx.env.create_string_latin1(bytes.as_slice())
|
||||
}
|
||||
|
||||
pub fn register_js(module: &mut Module) -> Result<()> {
|
||||
module.create_named_method("concatString", concat_string)?;
|
||||
module.create_named_method("concatLatin1String", concat_latin1_string)?;
|
||||
module.create_named_method("createLatin1", create_latin1)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue