///|
/// Errors produced by the LDAP message layer and the session layer. BER
/// errors are nested so callers can distinguish transport, protocol and
/// decode failures.
pub(all) suberror LdapError {
  Ber(BerError)
  Decode(String)
  Encode(String)
  Transport(String)
  NotBound
  PrematureClose
  UnexpectedOp(Int)
  InvalidMessageId(Int)
  Unsupported(String)
  InvalidFilter(String)
  InvalidDn(String)
  ScriptMismatch(String)
  TlsRequired
} derive(Eq, @debug.Debug)

///|
pub fn LdapError::to_string(self : LdapError) -> String {
  match self {
    Ber(e) => "ber: " + Error::to_string(e)
    Decode(msg) => "decode: \{msg}"
    Encode(msg) => "encode: \{msg}"
    Transport(msg) => "transport: \{msg}"
    NotBound => "not bound"
    PrematureClose => "connection closed before the operation completed"
    UnexpectedOp(tag) => "unexpected protocol op tag: \{tag}"
    InvalidMessageId(id) => "invalid message id: \{id}"
    Unsupported(what) => "unsupported: \{what}"
    InvalidFilter(msg) => "invalid filter: \{msg}"
    InvalidDn(msg) => "invalid dn: \{msg}"
    ScriptMismatch(msg) => "script mismatch: \{msg}"
    TlsRequired =>
      "confidentiality required: bind refused before StartTLS/LDAPS"
  }
}

///|
pub fn transport_error(msg : String) -> LdapError {
  Transport(msg)
}

///|
pub fn premature_close_error() -> LdapError {
  PrematureClose
}