use std::borrow::Borrow;
use std::fmt;
use std::hash::{Hash, Hasher};
use glaredb_parser::ast;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BinderIdent {
raw: String,
normalized: String,
quoted: bool,
}
impl BinderIdent {
pub fn new(raw: impl Into<String>, quoted: bool) -> Self {
let raw = raw.into();
let normalized = raw.to_ascii_lowercase();
BinderIdent {
raw,
normalized,
quoted,
}
}
pub fn is_quoted(&self) -> bool {
self.quoted
}
pub fn as_normalized_str(&self) -> &str {
&self.normalized
}
pub fn as_raw_str(&self) -> &str {
&self.raw
}
pub fn strict_eq(&self, other: &BinderIdent) -> bool {
if other.quoted {
return self.raw == other.raw;
}
self.normalized == other.normalized
}
}
impl From<String> for BinderIdent {
fn from(value: String) -> Self {
Self::new(value, false)
}
}
impl From<&str> for BinderIdent {
fn from(value: &str) -> Self {
Self::new(value, false)
}
}
impl From<ast::Ident> for BinderIdent {
fn from(value: ast::Ident) -> Self {
Self::new(value.value, value.quoted)
}
}
impl Borrow<str> for BinderIdent {
fn borrow(&self) -> &str {
&self.normalized
}
}
impl PartialEq for BinderIdent {
fn eq(&self, other: &Self) -> bool {
self.normalized == other.normalized
}
}
impl Eq for BinderIdent {}
impl Hash for BinderIdent {
fn hash<H: Hasher>(&self, state: &mut H) {
self.normalized.hash(state);
}
}
impl fmt::Display for BinderIdent {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.raw)
}
}
#[cfg(test)]
mod tests {
use std::collections::HashMap;
use super::*;
#[test]
fn basic_hash_map_unquoted_insert() {
let mut cols: HashMap<BinderIdent, usize> = HashMap::new();
cols.insert(BinderIdent::new("EmployeeName", false), 0);
assert_eq!(cols.get("employeename"), Some(&0));
assert_eq!(cols.get("EmployeeName"), None);
assert_eq!(cols.get(&BinderIdent::new("employeename", false)), Some(&0));
assert_eq!(cols.get(&BinderIdent::new("EmployeeName", false)), Some(&0));
assert_eq!(cols.get(&BinderIdent::new("EMPLOYEENAME", false)), Some(&0));
assert_eq!(cols.get(&BinderIdent::new("EmployeeName", true)), Some(&0));
}
#[test]
fn basic_hash_map_quoted_insert() {
let mut cols: HashMap<BinderIdent, usize> = HashMap::new();
cols.insert(BinderIdent::new("EmployeeName", true), 0);
assert_eq!(cols.get("employeename"), Some(&0));
assert_eq!(cols.get("EmployeeName"), None);
assert_eq!(cols.get(&BinderIdent::new("EmployeeName", true)), Some(&0));
assert_eq!(cols.get(&BinderIdent::new("employeename", false)), Some(&0));
assert_eq!(cols.get(&BinderIdent::new("EmployeeName", false)), Some(&0));
assert_eq!(cols.get(&BinderIdent::new("EMPLOYEENAME", false)), Some(&0));
}
}