use serde::{Deserialize, Serialize};
use crate::validate::{Validate, ValidationIssue};
#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
#[serde(transparent)]
pub struct PrimVec<T>(pub Vec<Option<T>>);
impl<T> PrimVec<T> {
#[must_use]
pub fn new() -> Self {
Self(Vec::new())
}
#[must_use]
pub fn len(&self) -> usize {
self.0.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn values(&self) -> impl Iterator<Item = &T> {
self.0.iter().filter_map(Option::as_ref)
}
pub fn iter(&self) -> std::slice::Iter<'_, Option<T>> {
self.0.iter()
}
pub fn push(&mut self, value: T) {
self.0.push(Some(value));
}
pub fn push_placeholder(&mut self) {
self.0.push(None);
}
#[must_use]
pub fn first_value(&self) -> Option<&T> {
self.values().next()
}
}
impl<T> From<Vec<T>> for PrimVec<T> {
fn from(values: Vec<T>) -> Self {
Self(values.into_iter().map(Some).collect())
}
}
impl<T> FromIterator<T> for PrimVec<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
Self(iter.into_iter().map(Some).collect())
}
}
impl<T> FromIterator<Option<T>> for PrimVec<T> {
fn from_iter<I: IntoIterator<Item = Option<T>>>(iter: I) -> Self {
Self(iter.into_iter().collect())
}
}
impl<T> IntoIterator for PrimVec<T> {
type Item = Option<T>;
type IntoIter = std::vec::IntoIter<Option<T>>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl<'a, T> IntoIterator for &'a PrimVec<T> {
type Item = &'a Option<T>;
type IntoIter = std::slice::Iter<'a, Option<T>>;
fn into_iter(self) -> Self::IntoIter {
self.0.iter()
}
}
impl<T: Validate> Validate for PrimVec<T> {
fn validate(&self) -> Vec<ValidationIssue> {
let mut issues = Vec::new();
for v in self.values() {
issues.extend(v.validate());
}
issues
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn null_positions_round_trip() {
let json = ::serde_json::json!(["a", null]);
let v: PrimVec<String> = ::serde_json::from_value(json.clone()).expect("nulls parse");
assert_eq!(v.len(), 2);
assert_eq!(v.values().collect::<Vec<_>>(), ["a"]);
assert_eq!(::serde_json::to_value(&v).expect("ser"), json);
}
#[test]
fn plain_arrays_are_unchanged() {
let json = ::serde_json::json!(["a", "b"]);
let v: PrimVec<String> = ::serde_json::from_value(json.clone()).expect("parse");
assert_eq!(v.values().count(), 2);
assert_eq!(::serde_json::to_value(&v).expect("ser"), json);
}
#[test]
fn construction_from_plain_values() {
let v: PrimVec<i32> = vec![1, 2].into();
assert_eq!(v.len(), 2);
let w: PrimVec<i32> = [1, 2].into_iter().collect();
assert_eq!(v, w);
}
}