diff options
Diffstat (limited to 'users/Profpatsch/arglib')
-rw-r--r-- | users/Profpatsch/arglib/ArglibNetencode.hs | 22 | ||||
-rw-r--r-- | users/Profpatsch/arglib/arglib-netencode.cabal | 65 | ||||
-rw-r--r-- | users/Profpatsch/arglib/netencode.nix | 81 |
3 files changed, 168 insertions, 0 deletions
diff --git a/users/Profpatsch/arglib/ArglibNetencode.hs b/users/Profpatsch/arglib/ArglibNetencode.hs new file mode 100644 index 0000000000..4531151ca2 --- /dev/null +++ b/users/Profpatsch/arglib/ArglibNetencode.hs @@ -0,0 +1,22 @@ +{-# LANGUAGE QuasiQuotes #-} + +module ArglibNetencode where + +import Data.Attoparsec.ByteString qualified as Atto +import ExecHelpers +import Label +import Netencode qualified +import PossehlAnalyticsPrelude +import System.Posix.Env.ByteString qualified as ByteEnv + +arglibNetencode :: CurrentProgramName -> Maybe (Label "arglibEnvvar" Text) -> IO Netencode.T +arglibNetencode progName mEnvvar = do + let envvar = mEnvvar <&> (.arglibEnvvar) & fromMaybe "ARGLIB_NETENCODE" & textToBytesUtf8 + ByteEnv.getEnv envvar >>= \case + Nothing -> dieUserError progName [fmt|could not read args, envvar {envvar} not set|] + Just bytes -> + case Atto.parseOnly (Netencode.netencodeParser <* Atto.endOfInput) bytes of + Left err -> dieEnvironmentProblem progName [fmt|arglib parsing error: {err}|] + Right t -> do + ByteEnv.unsetEnv envvar + pure t diff --git a/users/Profpatsch/arglib/arglib-netencode.cabal b/users/Profpatsch/arglib/arglib-netencode.cabal new file mode 100644 index 0000000000..42b524f405 --- /dev/null +++ b/users/Profpatsch/arglib/arglib-netencode.cabal @@ -0,0 +1,65 @@ +cabal-version: 3.0 +name: arglib-netencode +version: 0.1.0.0 +author: Profpatsch +maintainer: mail@profpatsch.de + +common common-options + ghc-options: + -Wall + -Wno-type-defaults + -Wunused-packages + -Wredundant-constraints + -fwarn-missing-deriving-strategies + + -- See https://downloads.haskell.org/ghc/latest/docs/users_guide/exts.html + -- for a description of all these extensions + default-extensions: + -- Infer Applicative instead of Monad where possible + ApplicativeDo + + -- Allow literal strings to be Text + OverloadedStrings + + -- Syntactic sugar improvements + LambdaCase + MultiWayIf + + -- Makes the (deprecated) usage of * instead of Data.Kind.Type an error + NoStarIsType + + -- Convenient and crucial to deal with ambiguous field names, commonly + -- known as RecordDotSyntax + OverloadedRecordDot + + -- does not export record fields as functions, use OverloadedRecordDot to access instead + NoFieldSelectors + + -- Record punning + RecordWildCards + + -- Improved Deriving + DerivingStrategies + DerivingVia + + -- Type-level strings + DataKinds + + -- to enable the `type` keyword in import lists (ormolu uses this automatically) + ExplicitNamespaces + + default-language: GHC2021 + + +library + import: common-options + exposed-modules: ArglibNetencode + + build-depends: + base >=4.15 && <5, + pa-prelude, + pa-label, + netencode, + exec-helpers, + attoparsec, + unix diff --git a/users/Profpatsch/arglib/netencode.nix b/users/Profpatsch/arglib/netencode.nix new file mode 100644 index 0000000000..83a94ddd6c --- /dev/null +++ b/users/Profpatsch/arglib/netencode.nix @@ -0,0 +1,81 @@ +{ depot, pkgs, lib, ... }: + +let + + # Add the given nix arguments to the program as ARGLIB_NETENCODE envvar + # + # Calls `netencode.gen.dwim` on the provided nix args value. + with-args = name: args: prog: depot.nix.writeExecline "${name}-with-args" { } [ + "export" + "ARGLIB_NETENCODE" + (depot.users.Profpatsch.netencode.gen.dwim args) + prog + ]; + + rust = depot.nix.writers.rustSimpleLib + { + name = "arglib-netencode"; + dependencies = [ + depot.users.Profpatsch.execline.exec-helpers + depot.users.Profpatsch.netencode.netencode-rs + ]; + } '' + extern crate netencode; + extern crate exec_helpers; + + use netencode::{T}; + use std::os::unix::ffi::OsStrExt; + + pub fn arglib_netencode(prog_name: &str, env: Option<&std::ffi::OsStr>) -> T { + let env = match env { + None => std::ffi::OsStr::from_bytes("ARGLIB_NETENCODE".as_bytes()), + Some(a) => a + }; + let t = match std::env::var_os(env) { + None => exec_helpers::die_user_error(prog_name, format!("could not read args, envvar {} not set", env.to_string_lossy())), + // TODO: good error handling for the different parser errors + Some(soup) => match netencode::parse::t_t(soup.as_bytes()) { + Ok((remainder, t)) => match remainder.is_empty() { + true => t, + false => exec_helpers::die_environment_problem(prog_name, format!("arglib: there was some unparsed bytes remaining: {:?}", remainder)) + }, + Err(err) => exec_helpers::die_environment_problem(prog_name, format!("arglib parsing error: {:?}", err)) + } + }; + std::env::remove_var(env); + t + } + ''; + + haskell = pkgs.haskellPackages.mkDerivation { + pname = "arglib-netencode"; + version = "0.1.0"; + + src = depot.users.Profpatsch.exactSource ./. [ + ./arglib-netencode.cabal + ./ArglibNetencode.hs + ]; + + libraryHaskellDepends = [ + pkgs.haskellPackages.pa-prelude + pkgs.haskellPackages.pa-label + pkgs.haskellPackages.pa-error-tree + depot.users.Profpatsch.netencode.netencode-hs + depot.users.Profpatsch.execline.exec-helpers-hs + ]; + + isLibrary = true; + license = lib.licenses.mit; + + + }; + + +in +depot.nix.readTree.drvTargets { + inherit + with-args + rust + haskell + ; +} |