use crate::{
ast::{expr::ConstExpr, generic::GenericParams, ty::TyKind},
common::{FieldId, SpanId, SymbolId, VariantId},
context::with_cx,
ffi::{FfiOption, FfiSlice},
span::{HasSpan, Span},
};
use super::{CommonItemData, Visibility};
#[repr(C)]
#[derive(Debug)]
pub struct UnionItem<'ast> {
data: CommonItemData<'ast>,
generics: GenericParams<'ast>,
fields: FfiSlice<'ast, ItemField<'ast>>,
}
super::impl_item_data!(UnionItem, Union);
impl<'ast> UnionItem<'ast> {
pub fn generics(&self) -> &GenericParams<'ast> {
&self.generics
}
pub fn fields(&self) -> &[ItemField<'ast>] {
self.fields.get()
}
}
#[cfg(feature = "driver-api")]
impl<'ast> UnionItem<'ast> {
pub fn new(data: CommonItemData<'ast>, generics: GenericParams<'ast>, fields: &'ast [ItemField<'ast>]) -> Self {
Self {
data,
generics,
fields: fields.into(),
}
}
}
#[repr(C)]
#[derive(Debug)]
pub struct EnumItem<'ast> {
data: CommonItemData<'ast>,
generics: GenericParams<'ast>,
variants: FfiSlice<'ast, EnumVariant<'ast>>,
}
super::impl_item_data!(EnumItem, Enum);
impl<'ast> EnumItem<'ast> {
pub fn generics(&self) -> &GenericParams<'ast> {
&self.generics
}
pub fn variants(&self) -> &[EnumVariant<'ast>] {
self.variants.get()
}
}
#[cfg(feature = "driver-api")]
impl<'ast> EnumItem<'ast> {
pub fn new(data: CommonItemData<'ast>, generics: GenericParams<'ast>, variants: &'ast [EnumVariant<'ast>]) -> Self {
Self {
data,
generics,
variants: variants.into(),
}
}
}
#[repr(C)]
#[derive(Debug)]
pub struct EnumVariant<'ast> {
id: VariantId,
ident: SymbolId,
span: SpanId,
kind: AdtKind<'ast>,
discriminant: FfiOption<ConstExpr<'ast>>,
}
impl<'ast> EnumVariant<'ast> {
pub fn id(&self) -> VariantId {
self.id
}
pub fn ident(&self) -> &str {
with_cx(self, |cx| cx.symbol_str(self.ident))
}
pub fn is_unit_variant(&self) -> bool {
matches!(self.kind, AdtKind::Unit)
}
pub fn is_tuple_variant(&self) -> bool {
matches!(self.kind, AdtKind::Tuple(..))
}
pub fn is_field_variant(&self) -> bool {
matches!(self.kind, AdtKind::Field(..))
}
pub fn fields(&self) -> &[ItemField<'ast>] {
match &self.kind {
AdtKind::Unit => &[],
AdtKind::Tuple(fields) | AdtKind::Field(fields) => fields.get(),
}
}
pub fn discriminant(&self) -> Option<&ConstExpr<'ast>> {
self.discriminant.get()
}
}
impl<'ast> HasSpan<'ast> for EnumVariant<'ast> {
fn span(&self) -> &Span<'ast> {
with_cx(self, |cx| cx.span(self.span))
}
}
crate::common::impl_identifiable_for!(EnumVariant<'ast>);
#[cfg(feature = "driver-api")]
impl<'ast> EnumVariant<'ast> {
pub fn new(
id: VariantId,
ident: SymbolId,
span: SpanId,
kind: AdtKind<'ast>,
discriminant: Option<ConstExpr<'ast>>,
) -> Self {
Self {
id,
ident,
span,
kind,
discriminant: discriminant.into(),
}
}
}
#[repr(C)]
#[derive(Debug)]
pub struct StructItem<'ast> {
data: CommonItemData<'ast>,
generics: GenericParams<'ast>,
kind: AdtKind<'ast>,
}
super::impl_item_data!(StructItem, Struct);
impl<'ast> StructItem<'ast> {
pub fn generics(&self) -> &GenericParams<'ast> {
&self.generics
}
pub fn is_unit_struct(&self) -> bool {
matches!(self.kind, AdtKind::Unit)
}
pub fn is_tuple_struct(&self) -> bool {
matches!(self.kind, AdtKind::Tuple(..))
}
pub fn is_field_struct(&self) -> bool {
matches!(self.kind, AdtKind::Field(..))
}
pub fn fields(&self) -> &[ItemField<'ast>] {
match &self.kind {
AdtKind::Unit => &[],
AdtKind::Tuple(fields) | AdtKind::Field(fields) => fields.get(),
}
}
}
#[cfg(feature = "driver-api")]
impl<'ast> StructItem<'ast> {
pub fn new(data: CommonItemData<'ast>, generics: GenericParams<'ast>, kind: AdtKind<'ast>) -> Self {
Self { data, generics, kind }
}
}
#[derive(Debug)]
#[allow(clippy::exhaustive_enums)]
#[cfg_attr(feature = "driver-api", visibility::make(pub))]
enum AdtKind<'ast> {
Unit,
Tuple(FfiSlice<'ast, ItemField<'ast>>),
Field(FfiSlice<'ast, ItemField<'ast>>),
}
impl<'ast> AdtKind<'ast> {
pub fn fields(self) -> &'ast [ItemField<'ast>] {
match self {
AdtKind::Tuple(fields) | AdtKind::Field(fields) => fields.get(),
AdtKind::Unit => &[],
}
}
}
#[repr(C)]
#[derive(Debug)]
pub struct ItemField<'ast> {
id: FieldId,
vis: Visibility<'ast>,
ident: SymbolId,
ty: TyKind<'ast>,
span: SpanId,
}
impl<'ast> ItemField<'ast> {
pub fn id(&self) -> FieldId {
self.id
}
pub fn visibility(&self) -> &Visibility<'ast> {
&self.vis
}
pub fn ident(&self) -> &str {
with_cx(self, |cx| cx.symbol_str(self.ident))
}
pub fn ty(&self) -> TyKind<'ast> {
self.ty
}
}
impl<'ast> HasSpan<'ast> for ItemField<'ast> {
fn span(&self) -> &Span<'ast> {
with_cx(self, |cx| cx.span(self.span))
}
}
crate::common::impl_identifiable_for!(ItemField<'ast>);
#[cfg(feature = "driver-api")]
impl<'ast> ItemField<'ast> {
pub fn new(id: FieldId, vis: Visibility<'ast>, ident: SymbolId, ty: TyKind<'ast>, span: SpanId) -> Self {
Self {
id,
vis,
ident,
ty,
span,
}
}
}