1
0
Fork 0
mirror of https://github.com/nix-community/home-manager.git synced 2025-11-08 19:46:05 +01:00
home-manager/modules/lib/gvariant.nix
Austin Horstman cba2f9ce95 treewide: reformat nixfmt-rfc-style
Reformat repository using new nixfmt-rfc-style.
2025-04-08 08:50:05 -07:00

208 lines
4.5 KiB
Nix

# A partial and basic implementation of GVariant formatted strings.
#
# Note, this API is not considered fully stable and it might therefore
# change in backwards incompatible ways without prior notice.
{ lib }:
let
inherit (lib)
concatMapStringsSep
concatStrings
escape
hasPrefix
head
replaceStrings
;
mkPrimitive = t: v: {
_type = "gvariant";
type = t;
value = v;
__toString = self: "@${self.type} ${toString self.value}";
};
type = {
arrayOf = t: "a${t}";
maybeOf = t: "m${t}";
tupleOf = ts: "(${concatStrings ts})";
dictionaryEntryOf = ts: "{${concatStrings ts}}";
string = "s";
boolean = "b";
uchar = "y";
int16 = "n";
uint16 = "q";
int32 = "i";
uint32 = "u";
int64 = "x";
uint64 = "t";
double = "d";
variant = "v";
};
# Returns the GVariant type of a given Nix value. If no type can be
# found for the value then the empty string is returned.
typeOf =
v:
with type;
if builtins.isBool v then
boolean
else if builtins.isInt v then
int32
else if builtins.isFloat v then
double
else if builtins.isString v then
string
else if builtins.isList v then
let
elemType = elemTypeOf v;
in
if elemType == "" then "" else arrayOf elemType
else if builtins.isAttrs v && v ? type then
v.type
else
"";
elemTypeOf = vs: if builtins.isList vs then if vs == [ ] then "" else typeOf (head vs) else "";
mkMaybe =
elemType: elem:
mkPrimitive (type.maybeOf elemType) elem
// {
__toString =
self: if self.value == null then "@${self.type} nothing" else "just ${toString self.value}";
};
in
rec {
inherit type typeOf;
isGVariant = v: v._type or "" == "gvariant";
isArray = hasPrefix "a";
isDictionaryEntry = hasPrefix "{";
isMaybe = hasPrefix "m";
isTuple = hasPrefix "(";
# Returns the GVariant value that most closely matches the given Nix
# value. If no GVariant value can be found then `null` is returned.
mkValue =
v:
if builtins.isBool v then
mkBoolean v
else if builtins.isInt v then
mkInt32 v
else if builtins.isFloat v then
mkDouble v
else if builtins.isString v then
mkString v
else if builtins.isList v then
if v == [ ] then mkArray type.string [ ] else mkArray (elemTypeOf v) v
else if builtins.isAttrs v && (v._type or "") == "gvariant" then
v
else
null;
mkArray =
elemType: elems:
mkPrimitive (type.arrayOf elemType) (map mkValue elems)
// {
__toString = self: "@${self.type} [${concatMapStringsSep "," toString self.value}]";
};
mkEmptyArray = elemType: mkArray elemType [ ];
mkVariant =
elem:
let
gvarElem = mkValue elem;
in
mkPrimitive type.variant gvarElem
// {
__toString = self: "@${self.type} <${toString self.value}>";
};
mkDictionaryEntry =
elems:
let
gvarElems = map mkValue elems;
dictionaryType = type.dictionaryEntryOf (map (e: e.type) gvarElems);
in
mkPrimitive dictionaryType gvarElems
// {
__toString = self: "@${self.type} {${concatMapStringsSep "," toString self.value}}";
};
mkNothing = elemType: mkMaybe elemType null;
mkJust =
elem:
let
gvarElem = mkValue elem;
in
mkMaybe gvarElem.type gvarElem;
mkTuple =
elems:
let
gvarElems = map mkValue elems;
tupleType = type.tupleOf (map (e: e.type) gvarElems);
in
mkPrimitive tupleType gvarElems
// {
__toString = self: "@${self.type} (${concatMapStringsSep "," toString self.value})";
};
mkBoolean =
v:
mkPrimitive type.boolean v
// {
__toString = self: if self.value then "true" else "false";
};
mkString =
v:
let
sanitize = s: replaceStrings [ "\n" ] [ "\\n" ] (escape [ "'" "\\" ] s);
in
mkPrimitive type.string v
// {
__toString = self: "'${sanitize self.value}'";
};
mkObjectpath =
v:
mkPrimitive type.string v
// {
__toString = self: "objectpath '${escape [ "'" ] self.value}'";
};
mkUchar = mkPrimitive type.uchar;
mkInt16 = mkPrimitive type.int16;
mkUint16 = mkPrimitive type.uint16;
mkInt32 =
v:
mkPrimitive type.int32 v
// {
__toString = self: toString self.value;
};
mkUint32 = mkPrimitive type.uint32;
mkInt64 = mkPrimitive type.int64;
mkUint64 = mkPrimitive type.uint64;
mkDouble =
v:
mkPrimitive type.double v
// {
__toString = self: toString self.value;
};
}