simdjson-rust 0.3.0-alpha.2

Rust bindings for the simdjson project.
Documentation
use std::{marker::PhantomData, ptr::NonNull};

use simdjson_sys as ffi;

use super::{document::Document, Element};
use crate::{macros::impl_drop, utils::string_view_struct_to_str};

pub struct Object<'a> {
    ptr: NonNull<ffi::SJ_DOM_object>,
    _doc: PhantomData<&'a Document>,
}

impl<'a> Object<'a> {
    pub fn new(ptr: NonNull<ffi::SJ_DOM_object>) -> Self {
        Self {
            ptr,
            _doc: PhantomData,
        }
    }
}

pub struct ObjectIter<'a> {
    begin: NonNull<ffi::SJ_DOM_object_iterator>,
    end: NonNull<ffi::SJ_DOM_object_iterator>,
    running: bool,
    _doc: PhantomData<&'a Document>,
}

impl<'a> ObjectIter<'a> {
    pub fn new(
        begin: NonNull<ffi::SJ_DOM_object_iterator>,
        end: NonNull<ffi::SJ_DOM_object_iterator>,
    ) -> Self {
        Self {
            begin,
            end,
            running: false,
            _doc: PhantomData,
        }
    }

    pub fn get(&self) -> (&'a str, Element<'a>) {
        let kv = unsafe { ffi::SJ_DOM_object_iterator_get(self.begin.as_ptr()) };
        let key = string_view_struct_to_str(kv.key);
        let value = Element::new(unsafe { NonNull::new_unchecked(kv.value) });
        (key, value)
    }

    pub fn step(&mut self) {
        unsafe { ffi::SJ_DOM_object_iterator_step(self.begin.as_ptr()) }
    }

    pub fn not_equal(&self) -> bool {
        unsafe { ffi::SJ_DOM_object_iterator_not_equal(self.begin.as_ptr(), self.end.as_ptr()) }
    }
}

impl<'a> Drop for ObjectIter<'a> {
    fn drop(&mut self) {
        unsafe {
            ffi::SJ_DOM_object_iterator_free(self.begin.as_ptr());
            ffi::SJ_DOM_object_iterator_free(self.end.as_ptr());
        }
    }
}

impl<'a> Iterator for ObjectIter<'a> {
    type Item = (&'a str, Element<'a>);

    fn next(&mut self) -> Option<Self::Item> {
        if self.running {
            self.step();
        }

        if self.not_equal() {
            self.running = true;
            Some(self.get())
        } else {
            None
        }
    }
}

impl_drop!(Object<'a>, ffi::SJ_DOM_object_free);