~zethra/freedesktop-entry-parser-js

1aba793e902c7d562f5970df14de3ecdf400d20b — zethra 7 months ago 51b3032
Made library work with both node and the browser

Signed-off-by: zethra <benaagoldberg@gmail.com>
4 files changed, 40 insertions(+), 60 deletions(-)

M Cargo.toml
M src/lib.rs
M tests/node.rs
M tests/web.rs
M Cargo.toml => Cargo.toml +1 -0
@@ 15,6 15,7 @@ crate-type = ["cdylib", "rlib"]
wasm-bindgen = "0.2"
js-sys = "0.3"
freedesktop_entry_parser = "0.2"
anyhow = "1.0"

[dev-dependencies]
wasm-bindgen-test = "0.3"

M src/lib.rs => src/lib.rs +37 -58
@@ 3,51 3,43 @@
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

use freedesktop_entry_parser as fep;
use js_sys::Uint8Array;
use std::convert::{TryFrom, TryInto};
use js_sys::{Array, Object, Reflect, Uint8Array};
use std::marker::PhantomPinned;
use std::pin::Pin;
use std::str::{from_utf8, Utf8Error};
use std::str::from_utf8;
use wasm_bindgen::prelude::*;

#[wasm_bindgen(module = "/src/structs.js")]
extern "C" {
    pub type Attr;

    #[wasm_bindgen(constructor)]
    pub fn new(name: String, value: String) -> Attr;

    pub type Section;

    #[wasm_bindgen(constructor)]
    pub fn new(name: String, value: Box<[JsValue]>) -> Section;
}

impl<'a> TryFrom<fep::AttrBytes<'a>> for Attr {
    type Error = Utf8Error;
    fn try_from(value: fep::AttrBytes) -> Result<Self, Self::Error> {
        Ok(Attr::new(
            from_utf8(value.name)?.to_owned(),
            from_utf8(value.value)?.to_owned(),
        ))
    }
fn attr_to_js<'a>(input: fep::AttrBytes<'a>) -> Result<JsValue, JsValue> {
    let name = from_utf8(input.name)
        .map_err(|e| e.to_string())
        .map_err(JsValue::from)?;
    let value = from_utf8(input.value)
        .map_err(|e| e.to_string())
        .map_err(JsValue::from)?;
    let obj = Object::new();
    Reflect::set(&obj, &"name".into(), &name.into())?;
    Reflect::set(&obj, &"value".into(), &value.into())?;
    Ok(obj.into())
}

impl<'a> TryFrom<fep::SectionBytes<'a>> for Section {
    type Error = Utf8Error;
    fn try_from(value: fep::SectionBytes) -> Result<Self, Self::Error> {
        Ok(Section::new(
            from_utf8(value.title)?.to_owned(),
            value
                .attrs
                .into_iter()
                .map(Attr::try_from)
                .collect::<Result<Vec<_>, _>>()?
                .into_iter()
                .map(JsValue::from)
                .collect(),
        ))
fn section_to_js<'a>(input: fep::SectionBytes<'a>) -> Result<JsValue, JsValue> {
    let title = from_utf8(input.title)
        .map_err(|e| e.to_string())
        .map_err(JsValue::from)?;
    let attrs = Array::new_with_length(input.attrs.len() as u32);
    for item in input
        .attrs
        .into_iter()
        .map(attr_to_js)
        .collect::<Result<Vec<_>, _>>()?
        .into_iter()
    {
        attrs.push(&item.into());
    }
    let obj = Object::new();
    Reflect::set(&obj, &"title".into(), &title.into())?;
    Reflect::set(&obj, &"attrs".into(), &attrs.into())?;
    Ok(obj.into())
}

struct IterWrapper {


@@ 60,23 52,19 @@ struct IterWrapper {
#[wasm_bindgen]
pub struct EntryIter {
    wrapper: Pin<Box<IterWrapper>>,
    cached: Option<Result<Section, JsValue>>,
    cached: Option<Result<JsValue, JsValue>>,
    done: bool,
}

#[wasm_bindgen]
impl EntryIter {
    #[wasm_bindgen(method)]
    pub fn next(&mut self) -> Result<Option<Section>, JsValue> {
    pub fn next(&mut self) -> Result<JsValue, JsValue> {
        if self.done {
            return Ok(None);
            return Ok(JsValue::NULL);
        }
        if self.cached.is_some() {
            let ret = match self.cached.take().unwrap() {
                Ok(item) => Ok(Some(item)),
                Err(e) => Err(e),
            };
            return ret;
            return self.cached.take().unwrap();
        }
        let mut iter = unsafe {
            let mut_ref = Pin::get_unchecked_mut(Pin::as_mut(&mut self.wrapper));


@@ 86,10 74,7 @@ impl EntryIter {
        std::mem::forget(iter);
        match opt {
            Some(res) => match res {
                Ok(item) => match item.try_into() {
                    Ok(s) => Ok(Some(s)),
                    Err(e) => Err(e.to_string().into()),
                },
                Ok(section) => section_to_js(section),
                Err(e) => {
                    self.done = true;
                    Err(e.to_string().into())


@@ 97,20 82,14 @@ impl EntryIter {
            },
            None => {
                self.done = true;
                Ok(None)
                Ok(JsValue::NULL)
            }
        }
    }

    #[wasm_bindgen(method)]
    pub fn done(&mut self) -> bool {
        self.cached = match self.next() {
            Ok(opt) => match opt {
                Some(item) => Some(Ok(item)),
                None => None,
            },
            Err(e) => Some(Err(e)),
        };
        self.cached = Some(self.next());
        self.done
    }
}

M tests/node.rs => tests/node.rs +1 -1
@@ 11,6 11,6 @@ fn parse_success() {
    let input = b"[apps]\nSize=48\nScale=1";
    let js_input = unsafe { Uint8Array::view(&input[..]) };
    let mut iter = parse_entry(js_input);
    let _section = iter.next().unwrap().unwrap();
    let _section = iter.next().unwrap();
    assert!(iter.done());
}

M tests/web.rs => tests/web.rs +1 -1
@@ 13,6 13,6 @@ fn parse_success() {
    let input = b"[apps]\nSize=48\nScale=1";
    let js_input = unsafe { Uint8Array::view(&input[..]) };
    let mut iter = parse_entry(js_input);
    let _section = iter.next().unwrap().unwrap();
    let _section = iter.next().unwrap();
    assert!(iter.done());
}