import gleam/dynamic.{type DecodeErrors, type Dynamic} import gleam/erlang/atom.{type Atom} import gleam/erlang/charlist.{type Charlist} import gleam/list @external(erlang, "io_lib", "format") fn erl_format(a: String, b: List(a)) -> Charlist /// Return a string representation of any term /// /// # Example /// /// ```gleam /// erlang.format(input) /// // -> {ok,<<"Gleam\n">>}% /// ``` pub fn format(term: any) -> String { charlist.to_string(erl_format("~p", [term])) } /// Returns a `BitArray` representing given value as an [Erlang external term][1]. /// /// /// /// [1]: https://www.erlang.org/doc/apps/erts/erl_ext_dist @external(erlang, "erlang", "term_to_binary") pub fn term_to_binary(a: a) -> BitArray type Safe { Safe } @external(erlang, "erlang", "binary_to_term") fn erl_binary_to_term(a: BitArray, b: List(Safe)) -> Dynamic /// Decodes a value from a `BitArray` representing an [Erlang external term][1]. /// /// /// /// [1]: https://www.erlang.org/doc/apps/erts/erl_ext_dist pub fn binary_to_term(binary: BitArray) -> Result(Dynamic, Nil) { case rescue(fn() { erl_binary_to_term(binary, [Safe]) }) { Ok(term) -> Ok(term) Error(_) -> Error(Nil) } } /// Decodes a value from a trusted `BitArray` representing an /// [Erlang external term][1]. /// /// *Warning*: Do not use this function with untrusted input, this can lead to /// Denial-of-Service. More information in the [Erlang documentation][2]. /// /// [1]: https://www.erlang.org/doc/apps/erts/erl_ext_dist /// [2]: https://www.erlang.org/doc/apps/erts/erlang.html#binary_to_term/1 pub fn unsafe_binary_to_term(binary: BitArray) -> Result(Dynamic, Nil) { case rescue(fn() { erl_binary_to_term(binary, []) }) { Ok(term) -> Ok(term) Error(_) -> Error(Nil) } } /// Error value returned by `get_line` function /// pub type GetLineError { Eof NoData } /// Reads a line from standard input with the given prompt. /// /// # Example /// /// ```gleam /// get_line("Language: ") /// // > Language: <- Gleam /// // -> Ok("Gleam\n") /// ``` @external(erlang, "gleam_erlang_ffi", "get_line") pub fn get_line(prompt prompt: String) -> Result(String, GetLineError) pub type TimeUnit { Second Millisecond Microsecond Nanosecond } /// Returns the current OS system time. /// /// @external(erlang, "os", "system_time") pub fn system_time(a: TimeUnit) -> Int /// Returns the current OS system time as a tuple of Ints /// /// @external(erlang, "os", "timestamp") pub fn erlang_timestamp() -> #(Int, Int, Int) /// Gleam doesn't offer any way to raise exceptions, but they may still occur /// due to bugs when working with unsafe code, such as when calling Erlang /// function. /// /// This function will catch any error thrown and convert it into a result /// rather than crashing the process. /// @external(erlang, "gleam_erlang_ffi", "rescue") pub fn rescue(a: fn() -> a) -> Result(a, Crash) pub type Crash { Exited(Dynamic) Thrown(Dynamic) Errored(Dynamic) } @external(erlang, "init", "get_plain_arguments") fn get_start_arguments() -> List(Charlist) /// Get the arguments given to the program when it was started. /// /// This is sometimes called `argv` in other languages. @deprecated("Please use the argv package instead") pub fn start_arguments() -> List(String) { get_start_arguments() |> list.map(charlist.to_string) } /// Starts an OTP application's process tree in the background, as well as /// the trees of any applications that the given application depends upon. An /// OTP application typically maps onto a Gleam or Hex package. /// /// Returns a list of the applications that were started. Calling this function /// for application that have already been started is a no-op so you do not need /// to check the application state beforehand. /// /// In Gleam we prefer to not use these implicit background process trees, but /// you will likely still need to start the trees of OTP applications written in /// other BEAM languages such as Erlang or Elixir, including those included by /// default with Erlang/OTP. /// /// For more information see the OTP documentation. /// - /// - /// @external(erlang, "gleam_erlang_ffi", "ensure_all_started") pub fn ensure_all_started( application application: Atom, ) -> Result(List(Atom), EnsureAllStartedError) pub type EnsureAllStartedError { UnknownApplication(name: Atom) ApplicationFailedToStart(name: Atom, reason: Dynamic) } /// A unique reference value. /// /// It holds no particular meaning or value, but unique values are often useful /// in programs are used heavily within both Gleam and Erlang's OTP frameworks. /// /// More can be read about references in the [Erlang documentation][1]. /// /// [1]: https://www.erlang.org/doc/efficiency_guide/advanced.html#unique_references /// pub type Reference /// Create a new unique reference. /// @external(erlang, "erlang", "make_ref") pub fn make_reference() -> Reference /// Checks to see whether a `Dynamic` value is a Reference, and return the Reference if /// it is. /// /// ## Examples /// /// ```gleam /// import gleam/dynamic /// /// reference_from_dynamic(dynamic.from(make_reference())) /// // -> Ok(Reference) /// ``` /// /// ```gleam /// import gleam/dynamic /// /// reference_from_dynamic(dynamic.from(123)) /// // -> Error([DecodeError(expected: "Reference", found: "Int", path: [])]) /// ``` @external(erlang, "gleam_erlang_ffi", "reference_from_dynamic") pub fn reference_from_dynamic( from from: Dynamic, ) -> Result(Reference, DecodeErrors) /// Returns the path of a package's `priv` directory, where extra non-Gleam /// or Erlang files are typically kept. /// /// Returns an error if no package was found with the given name. /// /// # Example /// /// ```gleam /// erlang.priv_directory("my_app") /// // -> Ok("/some/location/my_app/priv") /// ``` /// @external(erlang, "gleam_erlang_ffi", "priv_directory") pub fn priv_directory(name: String) -> Result(String, Nil)