Skip to main content

ergo_lib_c_core/
collections.rs

1//! Collections that can be manipulated from outside Rust
2
3use std::convert::{TryFrom, TryInto};
4
5use bounded_vec::{BoundedVec, BoundedVecOutOfBounds, OptBoundedVecToVec};
6
7use crate::error::*;
8use crate::util::{const_ptr_as_ref, mut_ptr_as_mut};
9
10pub struct Collection<T>(pub Vec<T>);
11pub type CollectionPtr<T> = *mut Collection<T>;
12pub type ConstCollectionPtr<T> = *const Collection<T>;
13
14pub unsafe fn collection_new<T>(collection_out: *mut CollectionPtr<T>) -> Result<(), Error> {
15    let collection_out = mut_ptr_as_mut(collection_out, "collection_out")?;
16    *collection_out = Box::into_raw(Box::new(Collection(vec![])));
17    Ok(())
18}
19
20pub unsafe fn collection_delete<T>(collection: CollectionPtr<T>) {
21    if !collection.is_null() {
22        let boxed = Box::from_raw(collection);
23        std::mem::drop(boxed);
24    }
25}
26
27pub unsafe fn collection_len<T>(collection: ConstCollectionPtr<T>) -> Result<usize, Error> {
28    let collection = const_ptr_as_ref(collection, "collection")?;
29    Ok(collection.0.len())
30}
31
32pub unsafe fn collection_get<T: Clone>(
33    collection: ConstCollectionPtr<T>,
34    index: usize,
35    elem_out: *mut *mut T,
36) -> Result<bool, Error> {
37    let collection = const_ptr_as_ref(collection, "collection")?;
38    let elem_out = mut_ptr_as_mut(elem_out, "elem_out")?;
39    if let Some(elem) = collection.0.get(index) {
40        *elem_out = Box::into_raw(Box::new(elem.clone()));
41        return Ok(true);
42    }
43    Ok(false)
44}
45
46pub unsafe fn collection_add<T: Clone>(
47    collection_out: CollectionPtr<T>,
48    elem: *const T,
49) -> Result<(), Error> {
50    let collection_out = mut_ptr_as_mut(collection_out, "collection_out")?;
51    let elem = const_ptr_as_ref(elem, "elem")?;
52    collection_out.0.push(elem.clone());
53    Ok(())
54}
55
56impl<T, S: Into<T>> From<Vec<S>> for Collection<T> {
57    fn from(vec: Vec<S>) -> Self {
58        Collection(vec.into_iter().map(Into::into).collect())
59    }
60}
61
62impl<T, S: Into<T>> From<Collection<S>> for Vec<T> {
63    fn from(vec: Collection<S>) -> Self {
64        vec.0.into_iter().map(Into::into).collect()
65    }
66}
67
68impl<T, S: Into<T> + Clone> From<&Collection<S>> for Vec<T> {
69    fn from(vec: &Collection<S>) -> Self {
70        vec.0.clone().into_iter().map(Into::into).collect()
71    }
72}
73
74impl<T, S: Into<T>, const L: usize, const U: usize> From<BoundedVec<S, L, U>> for Collection<T> {
75    fn from(bvec: BoundedVec<S, L, U>) -> Self {
76        bvec.to_vec().into()
77    }
78}
79
80impl<T, S: Into<T>, const L: usize, const U: usize> From<Option<BoundedVec<S, L, U>>>
81    for Collection<T>
82{
83    fn from(maybe_bvec: Option<BoundedVec<S, L, U>>) -> Self {
84        maybe_bvec.to_vec().into()
85    }
86}
87
88impl<T, S: Into<T> + Clone, const L: usize, const U: usize> TryFrom<Collection<S>>
89    for Option<BoundedVec<T, L, U>>
90{
91    type Error = BoundedVecOutOfBounds;
92
93    fn try_from(tokens: Collection<S>) -> Result<Self, Self::Error> {
94        (&tokens).try_into()
95    }
96}
97
98impl<T, S: Into<T> + Clone, const L: usize, const U: usize> TryFrom<&Collection<S>>
99    for Option<BoundedVec<T, L, U>>
100{
101    type Error = BoundedVecOutOfBounds;
102
103    fn try_from(tokens: &Collection<S>) -> Result<Self, Self::Error> {
104        if tokens.0.is_empty() {
105            Ok(None)
106        } else {
107            Ok(Some(
108                tokens
109                    .0
110                    .clone()
111                    .into_iter()
112                    .map(Into::into)
113                    .collect::<Vec<T>>()
114                    .try_into()?,
115            ))
116        }
117    }
118}