bluest 0.6.9

A cross-platform Bluetooth Low Energy (BLE) library
Documentation
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;

use windows::core::HSTRING;
use windows::Foundation::Collections::{IIterable, IIterable_Impl, IIterator, IIterator_Impl};

#[windows::core::implement(IIterable<HSTRING>)]
pub(super) struct StringVec(Arc<Vec<HSTRING>>);

#[windows::core::implement(IIterator<HSTRING>)]
pub(super) struct StringIterator {
    vec: Arc<Vec<HSTRING>>,
    pos: AtomicUsize,
}

impl StringVec {
    pub fn new(strings: Vec<HSTRING>) -> Self {
        Self(Arc::new(strings))
    }
}

impl IIterable_Impl<HSTRING> for StringVec {
    fn First(&self) -> windows::core::Result<windows::Foundation::Collections::IIterator<HSTRING>> {
        Ok(StringIterator {
            vec: self.0.clone(),
            pos: AtomicUsize::new(0),
        }
        .into())
    }
}

impl IIterator_Impl<HSTRING> for StringIterator {
    fn Current(&self) -> windows::core::Result<HSTRING> {
        let pos = self.pos.load(Ordering::Relaxed);
        if pos < self.vec.len() {
            Ok(self.vec[pos].clone())
        } else {
            Err(windows::core::Error::OK)
        }
    }

    fn HasCurrent(&self) -> windows::core::Result<bool> {
        let pos = self.pos.load(Ordering::Relaxed);
        Ok(pos < self.vec.len())
    }

    fn MoveNext(&self) -> windows::core::Result<bool> {
        let pos = self.pos.fetch_add(1, Ordering::Relaxed);
        Ok(pos + 1 < self.vec.len())
    }

    fn GetMany(&self, items: &mut [<HSTRING as windows::core::Type<HSTRING>>::Default]) -> windows::core::Result<u32> {
        let pos = self.pos.fetch_add(items.len(), Ordering::Relaxed);
        if pos < self.vec.len() {
            let len = (self.vec.len() - pos).min(items.len());
            items[0..len].clone_from_slice(&self.vec[pos..][..len]);
            Ok(len as u32)
        } else {
            Ok(0)
        }
    }
}