biscuit-auth 6.0.0

an authorization token with decentralized verification and offline attenuation
Documentation
/*
 * Copyright (c) 2019 Geoffroy Couprie <contact@geoffroycouprie.com> and Contributors to the Eclipse Foundation.
 * SPDX-License-Identifier: Apache-2.0
 */
use std::collections::HashSet;

use crate::{crypto::PublicKey, error};

#[derive(Clone, Debug, PartialEq, Eq, Default)]
pub struct PublicKeys {
    pub(crate) keys: Vec<PublicKey>,
}

impl PublicKeys {
    pub fn new() -> Self {
        PublicKeys { keys: vec![] }
    }

    pub fn from(keys: Vec<PublicKey>) -> Self {
        PublicKeys { keys }
    }

    pub fn extend(&mut self, other: &PublicKeys) -> Result<(), error::Format> {
        if !self.is_disjoint(other) {
            return Err(error::Format::PublicKeyTableOverlap);
        }
        self.keys.extend(other.keys.iter().cloned());
        Ok(())
    }

    pub fn insert(&mut self, k: &PublicKey) -> u64 {
        match self.keys.iter().position(|key| key == k) {
            Some(index) => index as u64,
            None => {
                self.keys.push(*k);
                (self.keys.len() - 1) as u64
            }
        }
    }

    pub fn insert_fallible(&mut self, k: &PublicKey) -> Result<u64, error::Format> {
        match self.keys.iter().position(|key| key == k) {
            Some(_) => Err(error::Format::PublicKeyTableOverlap),
            None => {
                self.keys.push(*k);
                Ok((self.keys.len() - 1) as u64)
            }
        }
    }

    pub fn get(&self, k: &PublicKey) -> Option<u64> {
        self.keys.iter().position(|key| key == k).map(|i| i as u64)
    }

    pub fn current_offset(&self) -> usize {
        self.keys.len()
    }

    pub fn split_at(&mut self, offset: usize) -> PublicKeys {
        let mut table = PublicKeys::new();
        table.keys = self.keys.split_off(offset);
        table
    }

    pub fn is_disjoint(&self, other: &PublicKeys) -> bool {
        let h1 = self.keys.iter().collect::<HashSet<_>>();
        let h2 = other.keys.iter().collect::<HashSet<_>>();

        h1.is_disjoint(&h2)
    }

    pub fn get_key(&self, i: u64) -> Option<&PublicKey> {
        self.keys.get(i as usize)
    }

    pub fn into_inner(self) -> Vec<PublicKey> {
        self.keys
    }
}