use crate::ast::expr::ConstExpr;
use crate::ast::generic::SynGenericParams;
use crate::ast::ty::SynTyKind;
use crate::ast::{FieldId, Span, SpanId, SymbolId, VariantId};
use crate::context::with_cx;
use crate::ffi::{FfiOption, FfiSlice};
use super::{CommonItemData, Visibility};
#[repr(C)]
#[derive(Debug)]
pub struct UnionItem<'ast> {
data: CommonItemData<'ast>,
generics: SynGenericParams<'ast>,
fields: FfiSlice<'ast, Field<'ast>>,
}
super::impl_item_data!(UnionItem, Union);
impl<'ast> UnionItem<'ast> {
pub fn generics(&self) -> &SynGenericParams<'ast> {
&self.generics
}
pub fn fields(&self) -> &[Field<'ast>] {
self.fields.get()
}
}
#[cfg(feature = "driver-api")]
impl<'ast> UnionItem<'ast> {
pub fn new(data: CommonItemData<'ast>, generics: SynGenericParams<'ast>, fields: &'ast [Field<'ast>]) -> Self {
Self {
data,
generics,
fields: fields.into(),
}
}
}
#[repr(C)]
#[derive(Debug)]
pub struct EnumItem<'ast> {
data: CommonItemData<'ast>,
generics: SynGenericParams<'ast>,
variants: FfiSlice<'ast, EnumVariant<'ast>>,
}
super::impl_item_data!(EnumItem, Enum);
impl<'ast> EnumItem<'ast> {
pub fn generics(&self) -> &SynGenericParams<'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: SynGenericParams<'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) -> &[Field<'ast>] {
match &self.kind {
AdtKind::Unit => &[],
AdtKind::Tuple(fields) | AdtKind::Field(fields) => fields.get(),
}
}
pub fn span(&self) -> &Span<'ast> {
with_cx(self, |cx| cx.span(self.span))
}
pub fn discriminant(&self) -> Option<&ConstExpr<'ast>> {
self.discriminant.get()
}
}
#[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: SynGenericParams<'ast>,
kind: AdtKind<'ast>,
}
super::impl_item_data!(StructItem, Struct);
impl<'ast> StructItem<'ast> {
pub fn generics(&self) -> &SynGenericParams<'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) -> &[Field<'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: SynGenericParams<'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, Field<'ast>>),
Field(FfiSlice<'ast, Field<'ast>>),
}
impl<'ast> AdtKind<'ast> {
pub fn fields(self) -> &'ast [Field<'ast>] {
match self {
AdtKind::Tuple(fields) | AdtKind::Field(fields) => fields.get(),
AdtKind::Unit => &[],
}
}
}
#[repr(C)]
#[derive(Debug)]
pub struct Field<'ast> {
id: FieldId,
vis: Visibility<'ast>,
ident: SymbolId,
ty: SynTyKind<'ast>,
span: SpanId,
}
impl<'ast> Field<'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) -> SynTyKind<'ast> {
self.ty
}
pub fn span(&self) -> &Span<'ast> {
with_cx(self, |cx| cx.span(self.span))
}
}
#[cfg(feature = "driver-api")]
impl<'ast> Field<'ast> {
pub fn new(id: FieldId, vis: Visibility<'ast>, ident: SymbolId, ty: SynTyKind<'ast>, span: SpanId) -> Self {
Self {
id,
vis,
ident,
ty,
span,
}
}
}