1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// Copyright 2016 Kyle Mayes
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::error::{Error};
use std::fmt;

use clang_sys::*;

use libc::{c_longlong};

use utility::{FromError};

//================================================
// Macros
//================================================

macro_rules! error {
    (
        $(#[$meta:meta])*
        pub enum $name:ident: $underlying:ty {
            $(#[$variantdoc:meta] $variant:ident = ($error:pat, $message:expr)), +,
        }
    ) => {
        $(#[$meta])*
        #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
        pub enum $name {
            $(#[$variantdoc] $variant), +
        }

        impl Error for $name {
            fn description(&self) -> &str {
                match *self {
                    $($name::$variant => $message), +
                }
            }
        }

        impl From<$name> for String {
            fn from(error: $name) -> String {
                error.description().into()
            }
        }

        impl FromError<$underlying> for $name {
            fn from_error(error: $underlying) -> Result<(), $name> {
                match error {
                    $($error => Err($name::$variant)), +,
                    _ => Ok(()),
                }
            }
        }

        impl fmt::Display for $name {
            fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                write!(formatter, "{}", self.description())
            }
        }
    };
}

//================================================
// Enums
//================================================

// AlignofError __________________________________

error! {
    /// Indicates the error that prevented determining the alignment of a type.
    pub enum AlignofError: c_longlong {
        /// The type is a dependent type.
        Dependent = (-3, "the type is a dependent type"),
        /// The type is an incomplete type.
        Incomplete = (-2, "the type is an incomplete type"),
    }
}

// OffsetofError _________________________________

error! {
    /// Indicates the error that prevented determining the offset of a field in a record type.
    pub enum OffsetofError: c_longlong {
        /// The record type is a dependent type.
        Dependent = (-3, "the record type is a dependent type"),
        /// The record type is an incomplete type.
        Incomplete = (-2, "the record type is an incomplete type"),
        /// The record type does not contain a field with the supplied name.
        Name = (-5, "the record type does not contain a field with the supplied name"),
        /// The record type has an invalid parent declaration.
        Parent = (-1, "the record type has an invalid parent declaration"),
    }
}

// SaveError _____________________________________

error! {
    /// Indicates the type of error that prevented the saving of a translation unit to an AST file.
    pub enum SaveError: CXSaveError {
        /// Errors in the translation unit prevented saving.
        Errors = (CXSaveError_InvalidTU, "errors in the translation unit prevented saving"),
        /// An unknown error occurred.
        Unknown = (CXSaveError_Unknown, "an unknown error occurred"),
    }
}

// SizeofError ___________________________________

error! {
    /// Indicates the error that prevented determining the size of a type.
    pub enum SizeofError: c_longlong {
        /// The type is a dependent type.
        Dependent = (-3, "the type is a dependent type"),
        /// The type is an incomplete type.
        Incomplete = (-2, "the type is an incomplete type"),
        /// The type is a variable size type.
        VariableSize = (-4, "the type is a variable size type"),
    }
}

// SourceError ___________________________________

error! {
    /// Indicates the type of error that prevented the loading of a translation unit from a source
    /// file.
    pub enum SourceError: CXErrorCode {
        /// An error occurred while deserializing an AST file.
        AstDeserialization = (CXError_ASTReadError, "AST deserialization failed"),
        /// `libclang` crashed.
        Crash = (CXError_Crashed, "`libclang` crashed"),
        /// An unknown error occurred.
        Unknown = (CXError_Failure, "an unknown error occurred"),
    }
}