summaryrefslogtreecommitdiff
path: root/vendor/logos-codegen/src/parser/ignore_flags.rs
diff options
context:
space:
mode:
authormo khan <mo@mokhan.ca>2025-07-15 16:37:08 -0600
committermo khan <mo@mokhan.ca>2025-07-17 16:30:22 -0600
commit45df4d0d9b577fecee798d672695fe24ff57fb1b (patch)
tree1b99bf645035b58e0d6db08c7a83521f41f7a75b /vendor/logos-codegen/src/parser/ignore_flags.rs
parentf94f79608393d4ab127db63cc41668445ef6b243 (diff)
feat: migrate from Cedar to SpiceDB authorization system
This is a major architectural change that replaces the Cedar policy-based authorization system with SpiceDB's relation-based authorization. Key changes: - Migrate from Rust to Go implementation - Replace Cedar policies with SpiceDB schema and relationships - Switch from envoy `ext_authz` with Cedar to SpiceDB permission checks - Update build system and dependencies for Go ecosystem - Maintain Envoy integration for external authorization This change enables more flexible permission modeling through SpiceDB's Google Zanzibar inspired relation-based system, supporting complex hierarchical permissions that were difficult to express in Cedar. Breaking change: Existing Cedar policies and Rust-based configuration will no longer work and need to be migrated to SpiceDB schema.
Diffstat (limited to 'vendor/logos-codegen/src/parser/ignore_flags.rs')
-rw-r--r--vendor/logos-codegen/src/parser/ignore_flags.rs499
1 files changed, 0 insertions, 499 deletions
diff --git a/vendor/logos-codegen/src/parser/ignore_flags.rs b/vendor/logos-codegen/src/parser/ignore_flags.rs
deleted file mode 100644
index 3a79d31b..00000000
--- a/vendor/logos-codegen/src/parser/ignore_flags.rs
+++ /dev/null
@@ -1,499 +0,0 @@
-use std::ops::{BitAnd, BitOr};
-
-use proc_macro2::{Ident, TokenStream, TokenTree};
-
-use crate::parser::Parser;
-use crate::util::is_punct;
-
-#[derive(Clone, Copy, PartialEq, Eq)]
-pub struct IgnoreFlags {
- bits: u8,
-}
-
-#[allow(non_upper_case_globals)]
-impl IgnoreFlags {
- pub const Empty: Self = Self::new(0x00);
- pub const IgnoreCase: Self = Self::new(0x01);
- pub const IgnoreAsciiCase: Self = Self::new(0x02);
-
- #[inline]
- pub const fn new(bits: u8) -> Self {
- Self { bits }
- }
-
- /// Enables a variant.
- #[inline]
- pub fn enable(&mut self, variant: Self) {
- self.bits |= variant.bits;
- }
-
- /// Checks if this `IgnoreFlags` contains *any* of the given variants.
- #[inline]
- pub fn contains(&self, variants: Self) -> bool {
- self.bits & variants.bits != 0
- }
-
- #[inline]
- pub fn is_empty(&self) -> bool {
- self.bits == 0
- }
-
- /// Parses an identifier an enables it for `self`.
- ///
- /// Valid inputs are (that produces `true`):
- /// * `"case"` (incompatible with `"ascii_case"`)
- /// * `"ascii_case"` (incompatible with `"case"`)
- ///
- /// An error causes this function to return `false` and emits an error to
- /// the given `Parser`.
- fn parse_ident(&mut self, ident: Ident, parser: &mut Parser) -> bool {
- match ident.to_string().as_str() {
- "case" => {
- if self.contains(Self::IgnoreAsciiCase) {
- parser.err(
- "\
- The flag \"case\" cannot be used along with \"ascii_case\"\
- ",
- ident.span(),
- );
- false
- } else {
- self.enable(Self::IgnoreCase);
- true
- }
- }
- "ascii_case" => {
- if self.contains(Self::IgnoreCase) {
- parser.err(
- "\
- The flag \"ascii_case\" cannot be used along with \"case\"\
- ",
- ident.span(),
- );
- false
- } else {
- self.enable(Self::IgnoreAsciiCase);
- true
- }
- }
- unknown => {
- parser.err(
- format!(
- "\
- Unknown flag: {}\n\
- \n\
- Expected one of: case, ascii_case\
- ",
- unknown
- ),
- ident.span(),
- );
- false
- }
- }
- }
-
- pub fn parse_group(&mut self, name: Ident, tokens: TokenStream, parser: &mut Parser) {
- // Little finite state machine to parse "<flag>(,<flag>)*,?"
-
- // FSM description for future maintenance
- // 0: Initial state
- // <flag> -> 1
- // _ -> error
- // 1: A flag was found
- // , -> 2
- // None -> done
- // _ -> error
- // 2: A comma was found (after a <flag>)
- // <flag> -> 1
- // None -> done
- // _ -> error
- let mut state = 0u8;
-
- let mut tokens = tokens.into_iter();
-
- loop {
- state = match state {
- 0 => match tokens.next() {
- Some(TokenTree::Ident(ident)) => {
- if self.parse_ident(ident, parser) {
- 1
- } else {
- return;
- }
- }
- _ => {
- parser.err(
- "\
- Invalid ignore flag\n\
- \n\
- Expected one of: case, ascii_case\
- ",
- name.span(),
- );
- return;
- }
- },
- 1 => match tokens.next() {
- Some(tt) if is_punct(&tt, ',') => 2,
- None => return,
- Some(unexpected_tt) => {
- parser.err(
- format!(
- "\
- Unexpected token: {:?}\
- ",
- unexpected_tt.to_string(),
- ),
- unexpected_tt.span(),
- );
- return;
- }
- },
- 2 => match tokens.next() {
- Some(TokenTree::Ident(ident)) => {
- if self.parse_ident(ident, parser) {
- 1
- } else {
- return;
- }
- }
- None => return,
- Some(unexpected_tt) => {
- parser.err(
- format!(
- "\
- Unexpected token: {:?}\
- ",
- unexpected_tt.to_string(),
- ),
- unexpected_tt.span(),
- );
- return;
- }
- },
- _ => unreachable!("Internal Error: invalid state ({})", state),
- }
- }
- }
-}
-
-impl BitOr for IgnoreFlags {
- type Output = Self;
-
- fn bitor(self, other: Self) -> Self {
- Self::new(self.bits | other.bits)
- }
-}
-
-impl BitAnd for IgnoreFlags {
- type Output = Self;
-
- fn bitand(self, other: Self) -> Self {
- Self::new(self.bits & other.bits)
- }
-}
-
-pub mod ascii_case {
- use regex_syntax::hir;
-
- use crate::mir::Mir;
- use crate::parser::Literal;
-
- macro_rules! literal {
- ($byte:expr) => {
- hir::Literal(Box::new([$byte]))
- };
- (@char $c:expr) => {
- hir::Literal(
- $c.encode_utf8(&mut [0; 4])
- .as_bytes()
- .to_vec()
- .into_boxed_slice(),
- )
- };
- }
-
- pub trait MakeAsciiCaseInsensitive {
- /// Creates a equivalent regular expression which ignore the letter casing
- /// of ascii characters.
- fn make_ascii_case_insensitive(self) -> Mir;
- }
-
- impl MakeAsciiCaseInsensitive for u8 {
- fn make_ascii_case_insensitive(self) -> Mir {
- if self.is_ascii_lowercase() {
- Mir::Alternation(vec![
- Mir::Literal(literal!(self - 32)),
- Mir::Literal(literal!(self)),
- ])
- } else if self.is_ascii_uppercase() {
- Mir::Alternation(vec![
- Mir::Literal(literal!(self)),
- Mir::Literal(literal!(self + 32)),
- ])
- } else {
- Mir::Literal(literal!(self))
- }
- }
- }
-
- impl MakeAsciiCaseInsensitive for char {
- fn make_ascii_case_insensitive(self) -> Mir {
- if self.is_ascii() {
- (self as u8).make_ascii_case_insensitive()
- } else {
- Mir::Literal(literal!(@char self))
- }
- }
- }
-
- impl MakeAsciiCaseInsensitive for hir::Literal {
- fn make_ascii_case_insensitive(self) -> Mir {
- Mir::Concat(
- self.0
- .iter()
- .map(|x| x.make_ascii_case_insensitive())
- .collect(),
- )
- }
- }
-
- impl MakeAsciiCaseInsensitive for hir::ClassBytes {
- fn make_ascii_case_insensitive(mut self) -> Mir {
- self.case_fold_simple();
- Mir::Class(hir::Class::Bytes(self))
- }
- }
-
- impl MakeAsciiCaseInsensitive for hir::ClassUnicode {
- fn make_ascii_case_insensitive(mut self) -> Mir {
- use std::cmp;
-
- // Manuall implementation to only perform the case folding on ascii characters.
-
- let mut ranges = Vec::new();
-
- for range in self.ranges() {
- #[inline]
- fn overlaps(st1: u8, end1: u8, st2: u8, end2: u8) -> bool {
- (st2 <= st1 && st1 <= end2) || (st1 <= st2 && st2 <= end1)
- }
-
- #[inline]
- fn make_ascii(c: char) -> Option<u8> {
- if c.is_ascii() {
- Some(c as u8)
- } else {
- None
- }
- }
-
- match (make_ascii(range.start()), make_ascii(range.end())) {
- (Some(start), Some(end)) => {
- if overlaps(b'a', b'z', start, end) {
- let lower = cmp::max(start, b'a');
- let upper = cmp::min(end, b'z');
- ranges.push(hir::ClassUnicodeRange::new(
- (lower - 32) as char,
- (upper - 32) as char,
- ))
- }
-
- if overlaps(b'A', b'Z', start, end) {
- let lower = cmp::max(start, b'A');
- let upper = cmp::min(end, b'Z');
- ranges.push(hir::ClassUnicodeRange::new(
- (lower + 32) as char,
- (upper + 32) as char,
- ))
- }
- }
- (Some(start), None) => {
- if overlaps(b'a', b'z', start, b'z') {
- let lower = cmp::max(start, b'a');
- ranges.push(hir::ClassUnicodeRange::new((lower - 32) as char, 'Z'))
- }
-
- if overlaps(b'A', b'Z', start, b'Z') {
- let lower = cmp::max(start, b'A');
- ranges.push(hir::ClassUnicodeRange::new((lower + 32) as char, 'Z'))
- }
- }
- _ => (),
- }
- }
-
- self.union(&hir::ClassUnicode::new(ranges));
-
- Mir::Class(hir::Class::Unicode(self))
- }
- }
-
- impl MakeAsciiCaseInsensitive for hir::Class {
- fn make_ascii_case_insensitive(self) -> Mir {
- match self {
- hir::Class::Bytes(b) => b.make_ascii_case_insensitive(),
- hir::Class::Unicode(u) => u.make_ascii_case_insensitive(),
- }
- }
- }
-
- impl MakeAsciiCaseInsensitive for &Literal {
- fn make_ascii_case_insensitive(self) -> Mir {
- match self {
- Literal::Bytes(bytes) => Mir::Concat(
- bytes
- .value()
- .into_iter()
- .map(|b| b.make_ascii_case_insensitive())
- .collect(),
- ),
- Literal::Utf8(s) => Mir::Concat(
- s.value()
- .chars()
- .map(|b| b.make_ascii_case_insensitive())
- .collect(),
- ),
- }
- }
- }
-
- impl MakeAsciiCaseInsensitive for Mir {
- fn make_ascii_case_insensitive(self) -> Mir {
- match self {
- Mir::Empty => Mir::Empty,
- Mir::Loop(l) => Mir::Loop(Box::new(l.make_ascii_case_insensitive())),
- Mir::Maybe(m) => Mir::Maybe(Box::new(m.make_ascii_case_insensitive())),
- Mir::Concat(c) => Mir::Concat(
- c.into_iter()
- .map(|m| m.make_ascii_case_insensitive())
- .collect(),
- ),
- Mir::Alternation(a) => Mir::Alternation(
- a.into_iter()
- .map(|m| m.make_ascii_case_insensitive())
- .collect(),
- ),
- Mir::Class(c) => c.make_ascii_case_insensitive(),
- Mir::Literal(l) => l.make_ascii_case_insensitive(),
- }
- }
- }
-
- #[cfg(test)]
- mod tests {
- use super::MakeAsciiCaseInsensitive;
- use crate::mir::{Class, Mir};
- use regex_syntax::hir::{ClassUnicode, ClassUnicodeRange};
-
- fn assert_range(in_s: char, in_e: char, expected: &[(char, char)]) {
- let range = ClassUnicodeRange::new(in_s, in_e);
- let class = ClassUnicode::new(vec![range]);
-
- let expected =
- ClassUnicode::new(expected.iter().map(|&(a, b)| ClassUnicodeRange::new(a, b)));
-
- if let Mir::Class(Class::Unicode(result)) = class.make_ascii_case_insensitive() {
- assert_eq!(result, expected);
- } else {
- panic!("Not a unicode class");
- };
- }
-
- #[test]
- fn no_letters_left() {
- assert_range(' ', '+', &[(' ', '+')]);
- }
-
- #[test]
- fn no_letters_right() {
- assert_range('{', '~', &[('{', '~')]);
- }
-
- #[test]
- fn no_letters_middle() {
- assert_range('[', '`', &[('[', '`')]);
- }
-
- #[test]
- fn lowercase_left_edge() {
- assert_range('a', 'd', &[('a', 'd'), ('A', 'D')]);
- }
-
- #[test]
- fn lowercase_right_edge() {
- assert_range('r', 'z', &[('r', 'z'), ('R', 'Z')]);
- }
-
- #[test]
- fn lowercase_total() {
- assert_range('a', 'z', &[('a', 'z'), ('A', 'Z')]);
- }
-
- #[test]
- fn uppercase_left_edge() {
- assert_range('A', 'D', &[('a', 'd'), ('A', 'D')]);
- }
-
- #[test]
- fn uppercase_right_edge() {
- assert_range('R', 'Z', &[('r', 'z'), ('R', 'Z')]);
- }
-
- #[test]
- fn uppercase_total() {
- assert_range('A', 'Z', &[('a', 'z'), ('A', 'Z')]);
- }
-
- #[test]
- fn lowercase_cross_left() {
- assert_range('[', 'h', &[('[', 'h'), ('A', 'H')]);
- }
-
- #[test]
- fn lowercase_cross_right() {
- assert_range('d', '}', &[('d', '}'), ('D', 'Z')]);
- }
-
- #[test]
- fn uppercase_cross_left() {
- assert_range(';', 'H', &[(';', 'H'), ('a', 'h')]);
- }
-
- #[test]
- fn uppercase_cross_right() {
- assert_range('T', ']', &[('t', 'z'), ('T', ']')]);
- }
-
- #[test]
- fn cross_both() {
- assert_range('X', 'c', &[('X', 'c'), ('x', 'z'), ('A', 'C')]);
- }
-
- #[test]
- fn all_letters() {
- assert_range('+', '|', &[('+', '|')]);
- }
-
- #[test]
- fn oob_all_letters() {
- assert_range('#', 'é', &[('#', 'é')]);
- }
-
- #[test]
- fn oob_from_uppercase() {
- assert_range('Q', 'é', &[('A', 'é')]);
- }
-
- #[test]
- fn oob_from_lowercase() {
- assert_range('q', 'é', &[('q', 'é'), ('Q', 'Z')]);
- }
-
- #[test]
- fn oob_no_letters() {
- assert_range('|', 'é', &[('|', 'é')]);
- }
- }
-}