    {-# LANGUAGE ConstrainedClassMethods #-}
    -- | Types for ZFS Properties.
    --
    -- Copyright 2016 Evan Cofsky <evan@theunixman.com>
    -- License: BSD 2-clause

    module Propellor.Types.ZFS where

    import Propellor.Types.ConfigurableValue
    import Utility.Split

    import Data.String
    import qualified Data.Set as Set
    import Data.List

    -- | A single ZFS filesystem.
    data ZFS = ZFS ZPool ZDataset deriving (Int -> ZFS -> ShowS
    [ZFS] -> ShowS
    ZFS -> String
    (Int -> ZFS -> ShowS)
    -> (ZFS -> String) -> ([ZFS] -> ShowS) -> Show ZFS
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> ZFS -> ShowS
    showsPrec :: Int -> ZFS -> ShowS
    $cshow :: ZFS -> String
    show :: ZFS -> String
    $cshowList :: [ZFS] -> ShowS
    showList :: [ZFS] -> ShowS
    Show, ZFS -> ZFS -> Bool
    (ZFS -> ZFS -> Bool) -> (ZFS -> ZFS -> Bool) -> Eq ZFS
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: ZFS -> ZFS -> Bool
    == :: ZFS -> ZFS -> Bool
    $c/= :: ZFS -> ZFS -> Bool
    /= :: ZFS -> ZFS -> Bool
    Eq, Eq ZFS
    Eq ZFS =>
    (ZFS -> ZFS -> Ordering)
    -> (ZFS -> ZFS -> Bool)
    -> (ZFS -> ZFS -> Bool)
    -> (ZFS -> ZFS -> Bool)
    -> (ZFS -> ZFS -> Bool)
    -> (ZFS -> ZFS -> ZFS)
    -> (ZFS -> ZFS -> ZFS)
    -> Ord ZFS
    ZFS -> ZFS -> Bool
    ZFS -> ZFS -> Ordering
    ZFS -> ZFS -> ZFS
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    $ccompare :: ZFS -> ZFS -> Ordering
    compare :: ZFS -> ZFS -> Ordering
    $c< :: ZFS -> ZFS -> Bool
    < :: ZFS -> ZFS -> Bool
    $c<= :: ZFS -> ZFS -> Bool
    <= :: ZFS -> ZFS -> Bool
    $c> :: ZFS -> ZFS -> Bool
    > :: ZFS -> ZFS -> Bool
    $c>= :: ZFS -> ZFS -> Bool
    >= :: ZFS -> ZFS -> Bool
    $cmax :: ZFS -> ZFS -> ZFS
    max :: ZFS -> ZFS -> ZFS
    $cmin :: ZFS -> ZFS -> ZFS
    min :: ZFS -> ZFS -> ZFS
    Ord)

    -- | Represents a zpool.
    data ZPool = ZPool String deriving (Int -> ZPool -> ShowS
    [ZPool] -> ShowS
    ZPool -> String
    (Int -> ZPool -> ShowS)
    -> (ZPool -> String) -> ([ZPool] -> ShowS) -> Show ZPool
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> ZPool -> ShowS
    showsPrec :: Int -> ZPool -> ShowS
    $cshow :: ZPool -> String
    show :: ZPool -> String
    $cshowList :: [ZPool] -> ShowS
    showList :: [ZPool] -> ShowS
    Show, ZPool -> ZPool -> Bool
    (ZPool -> ZPool -> Bool) -> (ZPool -> ZPool -> Bool) -> Eq ZPool
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: ZPool -> ZPool -> Bool
    == :: ZPool -> ZPool -> Bool
    $c/= :: ZPool -> ZPool -> Bool
    /= :: ZPool -> ZPool -> Bool
    Eq, Eq ZPool
    Eq ZPool =>
    (ZPool -> ZPool -> Ordering)
    -> (ZPool -> ZPool -> Bool)
    -> (ZPool -> ZPool -> Bool)
    -> (ZPool -> ZPool -> Bool)
    -> (ZPool -> ZPool -> Bool)
    -> (ZPool -> ZPool -> ZPool)
    -> (ZPool -> ZPool -> ZPool)
    -> Ord ZPool
    ZPool -> ZPool -> Bool
    ZPool -> ZPool -> Ordering
    ZPool -> ZPool -> ZPool
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    $ccompare :: ZPool -> ZPool -> Ordering
    compare :: ZPool -> ZPool -> Ordering
    $c< :: ZPool -> ZPool -> Bool
    < :: ZPool -> ZPool -> Bool
    $c<= :: ZPool -> ZPool -> Bool
    <= :: ZPool -> ZPool -> Bool
    $c> :: ZPool -> ZPool -> Bool
    > :: ZPool -> ZPool -> Bool
    $c>= :: ZPool -> ZPool -> Bool
    >= :: ZPool -> ZPool -> Bool
    $cmax :: ZPool -> ZPool -> ZPool
    max :: ZPool -> ZPool -> ZPool
    $cmin :: ZPool -> ZPool -> ZPool
    min :: ZPool -> ZPool -> ZPool
    Ord)

    -- | Represents a dataset in a zpool.
    --
    -- Can be constructed from a / separated string.
    data ZDataset = ZDataset [String] deriving (ZDataset -> ZDataset -> Bool
    (ZDataset -> ZDataset -> Bool)
    -> (ZDataset -> ZDataset -> Bool) -> Eq ZDataset
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: ZDataset -> ZDataset -> Bool
    == :: ZDataset -> ZDataset -> Bool
    $c/= :: ZDataset -> ZDataset -> Bool
    /= :: ZDataset -> ZDataset -> Bool
    Eq, Eq ZDataset
    Eq ZDataset =>
    (ZDataset -> ZDataset -> Ordering)
    -> (ZDataset -> ZDataset -> Bool)
    -> (ZDataset -> ZDataset -> Bool)
    -> (ZDataset -> ZDataset -> Bool)
    -> (ZDataset -> ZDataset -> Bool)
    -> (ZDataset -> ZDataset -> ZDataset)
    -> (ZDataset -> ZDataset -> ZDataset)
    -> Ord ZDataset
    ZDataset -> ZDataset -> Bool
    ZDataset -> ZDataset -> Ordering
    ZDataset -> ZDataset -> ZDataset
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    $ccompare :: ZDataset -> ZDataset -> Ordering
    compare :: ZDataset -> ZDataset -> Ordering
    $c< :: ZDataset -> ZDataset -> Bool
    < :: ZDataset -> ZDataset -> Bool
    $c<= :: ZDataset -> ZDataset -> Bool
    <= :: ZDataset -> ZDataset -> Bool
    $c> :: ZDataset -> ZDataset -> Bool
    > :: ZDataset -> ZDataset -> Bool
    $c>= :: ZDataset -> ZDataset -> Bool
    >= :: ZDataset -> ZDataset -> Bool
    $cmax :: ZDataset -> ZDataset -> ZDataset
    max :: ZDataset -> ZDataset -> ZDataset
    $cmin :: ZDataset -> ZDataset -> ZDataset
    min :: ZDataset -> ZDataset -> ZDataset
    Ord)

    type ZFSProperties = Set.Set ZFSProperty

    fromList :: [ZFSProperty] -> ZFSProperties
    fromList :: [ZFSProperty] -> ZFSProperties
    fromList = [ZFSProperty] -> ZFSProperties
    forall a. Ord a => [a] -> Set a
    Set.fromList

    toPropertyList :: ZFSProperties -> [(String, String)]
    toPropertyList :: ZFSProperties -> [(String, String)]
    toPropertyList = (ZFSProperty -> [(String, String)] -> [(String, String)])
    -> [(String, String)] -> ZFSProperties -> [(String, String)]
    forall a b. (a -> b -> b) -> b -> Set a -> b
    Set.foldr (\ZFSProperty
    p [(String, String)]
    l -> [(String, String)]
    l [(String, String)] -> [(String, String)] -> [(String, String)]
    forall a. [a] -> [a] -> [a]
    ++ [ZFSProperty -> (String, String)
    toPair ZFSProperty
    p]) []

    fromPropertyList :: [(String, String)] -> ZFSProperties
    fromPropertyList :: [(String, String)] -> ZFSProperties
    fromPropertyList [(String, String)]
    props =
    	[ZFSProperty] -> ZFSProperties
    forall a. Ord a => [a] -> Set a
    Set.fromList ([ZFSProperty] -> ZFSProperties) -> [ZFSProperty] -> ZFSProperties
    forall a b. (a -> b) -> a -> b
    $ ((String, String) -> ZFSProperty)
    -> [(String, String)] -> [ZFSProperty]
    forall a b. (a -> b) -> [a] -> [b]
    map (String, String) -> ZFSProperty
    fromPair [(String, String)]
    props

    zfsName :: ZFS -> String
    zfsName :: ZFS -> String
    zfsName (ZFS (ZPool String
    pool) ZDataset
    dataset) = String -> [String] -> String
    forall a. [a] -> [[a]] -> [a]
    intercalate String
    "/" [String
    pool, ZDataset -> String
    forall a. Show a => a -> String
    show ZDataset
    dataset]

    instance ConfigurableValue ZDataset where
    	val :: ZDataset -> String
    val (ZDataset [String]
    paths) = String -> [String] -> String
    forall a. [a] -> [[a]] -> [a]
    intercalate String
    "/" [String]
    paths

    instance Show ZDataset where
    	show :: ZDataset -> String
    show = ZDataset -> String
    forall t. ConfigurableValue t => t -> String
    val

    instance IsString ZDataset where
    	fromString :: String -> ZDataset
    fromString String
    s = [String] -> ZDataset
    ZDataset ([String] -> ZDataset) -> [String] -> ZDataset
    forall a b. (a -> b) -> a -> b
    $ Char -> String -> [String]
    forall c. Eq c => c -> [c] -> [[c]]
    splitc Char
    '/' String
    s

    instance IsString ZPool where
    	fromString :: String -> ZPool
    fromString String
    p = String -> ZPool
    ZPool String
    p

    class Value a where
    	toValue :: a -> String
    	fromValue :: (IsString a) => String -> a
    	fromValue = String -> a
    forall a. IsString a => String -> a
    fromString

    data ZFSYesNo = ZFSYesNo Bool deriving (Int -> ZFSYesNo -> ShowS
    [ZFSYesNo] -> ShowS
    ZFSYesNo -> String
    (Int -> ZFSYesNo -> ShowS)
    -> (ZFSYesNo -> String) -> ([ZFSYesNo] -> ShowS) -> Show ZFSYesNo
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> ZFSYesNo -> ShowS
    showsPrec :: Int -> ZFSYesNo -> ShowS
    $cshow :: ZFSYesNo -> String
    show :: ZFSYesNo -> String
    $cshowList :: [ZFSYesNo] -> ShowS
    showList :: [ZFSYesNo] -> ShowS
    Show, ZFSYesNo -> ZFSYesNo -> Bool
    (ZFSYesNo -> ZFSYesNo -> Bool)
    -> (ZFSYesNo -> ZFSYesNo -> Bool) -> Eq ZFSYesNo
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: ZFSYesNo -> ZFSYesNo -> Bool
    == :: ZFSYesNo -> ZFSYesNo -> Bool
    $c/= :: ZFSYesNo -> ZFSYesNo -> Bool
    /= :: ZFSYesNo -> ZFSYesNo -> Bool
    Eq, Eq ZFSYesNo
    Eq ZFSYesNo =>
    (ZFSYesNo -> ZFSYesNo -> Ordering)
    -> (ZFSYesNo -> ZFSYesNo -> Bool)
    -> (ZFSYesNo -> ZFSYesNo -> Bool)
    -> (ZFSYesNo -> ZFSYesNo -> Bool)
    -> (ZFSYesNo -> ZFSYesNo -> Bool)
    -> (ZFSYesNo -> ZFSYesNo -> ZFSYesNo)
    -> (ZFSYesNo -> ZFSYesNo -> ZFSYesNo)
    -> Ord ZFSYesNo
    ZFSYesNo -> ZFSYesNo -> Bool
    ZFSYesNo -> ZFSYesNo -> Ordering
    ZFSYesNo -> ZFSYesNo -> ZFSYesNo
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    $ccompare :: ZFSYesNo -> ZFSYesNo -> Ordering
    compare :: ZFSYesNo -> ZFSYesNo -> Ordering
    $c< :: ZFSYesNo -> ZFSYesNo -> Bool
    < :: ZFSYesNo -> ZFSYesNo -> Bool
    $c<= :: ZFSYesNo -> ZFSYesNo -> Bool
    <= :: ZFSYesNo -> ZFSYesNo -> Bool
    $c> :: ZFSYesNo -> ZFSYesNo -> Bool
    > :: ZFSYesNo -> ZFSYesNo -> Bool
    $c>= :: ZFSYesNo -> ZFSYesNo -> Bool
    >= :: ZFSYesNo -> ZFSYesNo -> Bool
    $cmax :: ZFSYesNo -> ZFSYesNo -> ZFSYesNo
    max :: ZFSYesNo -> ZFSYesNo -> ZFSYesNo
    $cmin :: ZFSYesNo -> ZFSYesNo -> ZFSYesNo
    min :: ZFSYesNo -> ZFSYesNo -> ZFSYesNo
    Ord)
    data ZFSOnOff = ZFSOnOff Bool deriving (Int -> ZFSOnOff -> ShowS
    [ZFSOnOff] -> ShowS
    ZFSOnOff -> String
    (Int -> ZFSOnOff -> ShowS)
    -> (ZFSOnOff -> String) -> ([ZFSOnOff] -> ShowS) -> Show ZFSOnOff
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> ZFSOnOff -> ShowS
    showsPrec :: Int -> ZFSOnOff -> ShowS
    $cshow :: ZFSOnOff -> String
    show :: ZFSOnOff -> String
    $cshowList :: [ZFSOnOff] -> ShowS
    showList :: [ZFSOnOff] -> ShowS
    Show, ZFSOnOff -> ZFSOnOff -> Bool
    (ZFSOnOff -> ZFSOnOff -> Bool)
    -> (ZFSOnOff -> ZFSOnOff -> Bool) -> Eq ZFSOnOff
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: ZFSOnOff -> ZFSOnOff -> Bool
    == :: ZFSOnOff -> ZFSOnOff -> Bool
    $c/= :: ZFSOnOff -> ZFSOnOff -> Bool
    /= :: ZFSOnOff -> ZFSOnOff -> Bool
    Eq, Eq ZFSOnOff
    Eq ZFSOnOff =>
    (ZFSOnOff -> ZFSOnOff -> Ordering)
    -> (ZFSOnOff -> ZFSOnOff -> Bool)
    -> (ZFSOnOff -> ZFSOnOff -> Bool)
    -> (ZFSOnOff -> ZFSOnOff -> Bool)
    -> (ZFSOnOff -> ZFSOnOff -> Bool)
    -> (ZFSOnOff -> ZFSOnOff -> ZFSOnOff)
    -> (ZFSOnOff -> ZFSOnOff -> ZFSOnOff)
    -> Ord ZFSOnOff
    ZFSOnOff -> ZFSOnOff -> Bool
    ZFSOnOff -> ZFSOnOff -> Ordering
    ZFSOnOff -> ZFSOnOff -> ZFSOnOff
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    $ccompare :: ZFSOnOff -> ZFSOnOff -> Ordering
    compare :: ZFSOnOff -> ZFSOnOff -> Ordering
    $c< :: ZFSOnOff -> ZFSOnOff -> Bool
    < :: ZFSOnOff -> ZFSOnOff -> Bool
    $c<= :: ZFSOnOff -> ZFSOnOff -> Bool
    <= :: ZFSOnOff -> ZFSOnOff -> Bool
    $c> :: ZFSOnOff -> ZFSOnOff -> Bool
    > :: ZFSOnOff -> ZFSOnOff -> Bool
    $c>= :: ZFSOnOff -> ZFSOnOff -> Bool
    >= :: ZFSOnOff -> ZFSOnOff -> Bool
    $cmax :: ZFSOnOff -> ZFSOnOff -> ZFSOnOff
    max :: ZFSOnOff -> ZFSOnOff -> ZFSOnOff
    $cmin :: ZFSOnOff -> ZFSOnOff -> ZFSOnOff
    min :: ZFSOnOff -> ZFSOnOff -> ZFSOnOff
    Ord)
    data ZFSSize = ZFSSize Integer deriving (Int -> ZFSSize -> ShowS
    [ZFSSize] -> ShowS
    ZFSSize -> String
    (Int -> ZFSSize -> ShowS)
    -> (ZFSSize -> String) -> ([ZFSSize] -> ShowS) -> Show ZFSSize
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> ZFSSize -> ShowS
    showsPrec :: Int -> ZFSSize -> ShowS
    $cshow :: ZFSSize -> String
    show :: ZFSSize -> String
    $cshowList :: [ZFSSize] -> ShowS
    showList :: [ZFSSize] -> ShowS
    Show, ZFSSize -> ZFSSize -> Bool
    (ZFSSize -> ZFSSize -> Bool)
    -> (ZFSSize -> ZFSSize -> Bool) -> Eq ZFSSize
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: ZFSSize -> ZFSSize -> Bool
    == :: ZFSSize -> ZFSSize -> Bool
    $c/= :: ZFSSize -> ZFSSize -> Bool
    /= :: ZFSSize -> ZFSSize -> Bool
    Eq, Eq ZFSSize
    Eq ZFSSize =>
    (ZFSSize -> ZFSSize -> Ordering)
    -> (ZFSSize -> ZFSSize -> Bool)
    -> (ZFSSize -> ZFSSize -> Bool)
    -> (ZFSSize -> ZFSSize -> Bool)
    -> (ZFSSize -> ZFSSize -> Bool)
    -> (ZFSSize -> ZFSSize -> ZFSSize)
    -> (ZFSSize -> ZFSSize -> ZFSSize)
    -> Ord ZFSSize
    ZFSSize -> ZFSSize -> Bool
    ZFSSize -> ZFSSize -> Ordering
    ZFSSize -> ZFSSize -> ZFSSize
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    $ccompare :: ZFSSize -> ZFSSize -> Ordering
    compare :: ZFSSize -> ZFSSize -> Ordering
    $c< :: ZFSSize -> ZFSSize -> Bool
    < :: ZFSSize -> ZFSSize -> Bool
    $c<= :: ZFSSize -> ZFSSize -> Bool
    <= :: ZFSSize -> ZFSSize -> Bool
    $c> :: ZFSSize -> ZFSSize -> Bool
    > :: ZFSSize -> ZFSSize -> Bool
    $c>= :: ZFSSize -> ZFSSize -> Bool
    >= :: ZFSSize -> ZFSSize -> Bool
    $cmax :: ZFSSize -> ZFSSize -> ZFSSize
    max :: ZFSSize -> ZFSSize -> ZFSSize
    $cmin :: ZFSSize -> ZFSSize -> ZFSSize
    min :: ZFSSize -> ZFSSize -> ZFSSize
    Ord)
    data ZFSString = ZFSString String deriving (Int -> ZFSString -> ShowS
    [ZFSString] -> ShowS
    ZFSString -> String
    (Int -> ZFSString -> ShowS)
    -> (ZFSString -> String)
    -> ([ZFSString] -> ShowS)
    -> Show ZFSString
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> ZFSString -> ShowS
    showsPrec :: Int -> ZFSString -> ShowS
    $cshow :: ZFSString -> String
    show :: ZFSString -> String
    $cshowList :: [ZFSString] -> ShowS
    showList :: [ZFSString] -> ShowS
    Show, ZFSString -> ZFSString -> Bool
    (ZFSString -> ZFSString -> Bool)
    -> (ZFSString -> ZFSString -> Bool) -> Eq ZFSString
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: ZFSString -> ZFSString -> Bool
    == :: ZFSString -> ZFSString -> Bool
    $c/= :: ZFSString -> ZFSString -> Bool
    /= :: ZFSString -> ZFSString -> Bool
    Eq, Eq ZFSString
    Eq ZFSString =>
    (ZFSString -> ZFSString -> Ordering)
    -> (ZFSString -> ZFSString -> Bool)
    -> (ZFSString -> ZFSString -> Bool)
    -> (ZFSString -> ZFSString -> Bool)
    -> (ZFSString -> ZFSString -> Bool)
    -> (ZFSString -> ZFSString -> ZFSString)
    -> (ZFSString -> ZFSString -> ZFSString)
    -> Ord ZFSString
    ZFSString -> ZFSString -> Bool
    ZFSString -> ZFSString -> Ordering
    ZFSString -> ZFSString -> ZFSString
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    $ccompare :: ZFSString -> ZFSString -> Ordering
    compare :: ZFSString -> ZFSString -> Ordering
    $c< :: ZFSString -> ZFSString -> Bool
    < :: ZFSString -> ZFSString -> Bool
    $c<= :: ZFSString -> ZFSString -> Bool
    <= :: ZFSString -> ZFSString -> Bool
    $c> :: ZFSString -> ZFSString -> Bool
    > :: ZFSString -> ZFSString -> Bool
    $c>= :: ZFSString -> ZFSString -> Bool
    >= :: ZFSString -> ZFSString -> Bool
    $cmax :: ZFSString -> ZFSString -> ZFSString
    max :: ZFSString -> ZFSString -> ZFSString
    $cmin :: ZFSString -> ZFSString -> ZFSString
    min :: ZFSString -> ZFSString -> ZFSString
    Ord)

    instance Value ZFSYesNo where
    	toValue :: ZFSYesNo -> String
    toValue (ZFSYesNo Bool
    True) = String
    "yes"
    	toValue (ZFSYesNo Bool
    False) = String
    "no"

    instance Value ZFSOnOff where
    	toValue :: ZFSOnOff -> String
    toValue (ZFSOnOff Bool
    True) = String
    "on"
    	toValue (ZFSOnOff Bool
    False) = String
    "off"

    instance Value ZFSSize where
    	toValue :: ZFSSize -> String
    toValue (ZFSSize Integer
    s) = Integer -> String
    forall a. Show a => a -> String
    show Integer
    s

    instance Value ZFSString where
    	toValue :: ZFSString -> String
    toValue (ZFSString String
    s) = String
    s

    instance IsString ZFSString where
    	fromString :: String -> ZFSString
    fromString = String -> ZFSString
    ZFSString

    instance IsString ZFSYesNo where
    	fromString :: String -> ZFSYesNo
    fromString String
    "yes" = Bool -> ZFSYesNo
    ZFSYesNo Bool
    True
    	fromString String
    "no" = Bool -> ZFSYesNo
    ZFSYesNo Bool
    False
    	fromString String
    _ = String -> ZFSYesNo
    forall a. HasCallStack => String -> a
    error String
    "Not yes or no"

    instance IsString ZFSOnOff where
    	fromString :: String -> ZFSOnOff
    fromString String
    "on" = Bool -> ZFSOnOff
    ZFSOnOff Bool
    True
    	fromString String
    "off" = Bool -> ZFSOnOff
    ZFSOnOff Bool
    False
    	fromString String
    _ = String -> ZFSOnOff
    forall a. HasCallStack => String -> a
    error String
    "Not on or off"

    data ZFSACLInherit = AIDiscard | AINoAllow | AISecure | AIPassthrough deriving (Int -> ZFSACLInherit -> ShowS
    [ZFSACLInherit] -> ShowS
    ZFSACLInherit -> String
    (Int -> ZFSACLInherit -> ShowS)
    -> (ZFSACLInherit -> String)
    -> ([ZFSACLInherit] -> ShowS)
    -> Show ZFSACLInherit
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> ZFSACLInherit -> ShowS
    showsPrec :: Int -> ZFSACLInherit -> ShowS
    $cshow :: ZFSACLInherit -> String
    show :: ZFSACLInherit -> String
    $cshowList :: [ZFSACLInherit] -> ShowS
    showList :: [ZFSACLInherit] -> ShowS
    Show, ZFSACLInherit -> ZFSACLInherit -> Bool
    (ZFSACLInherit -> ZFSACLInherit -> Bool)
    -> (ZFSACLInherit -> ZFSACLInherit -> Bool) -> Eq ZFSACLInherit
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: ZFSACLInherit -> ZFSACLInherit -> Bool
    == :: ZFSACLInherit -> ZFSACLInherit -> Bool
    $c/= :: ZFSACLInherit -> ZFSACLInherit -> Bool
    /= :: ZFSACLInherit -> ZFSACLInherit -> Bool
    Eq, Eq ZFSACLInherit
    Eq ZFSACLInherit =>
    (ZFSACLInherit -> ZFSACLInherit -> Ordering)
    -> (ZFSACLInherit -> ZFSACLInherit -> Bool)
    -> (ZFSACLInherit -> ZFSACLInherit -> Bool)
    -> (ZFSACLInherit -> ZFSACLInherit -> Bool)
    -> (ZFSACLInherit -> ZFSACLInherit -> Bool)
    -> (ZFSACLInherit -> ZFSACLInherit -> ZFSACLInherit)
    -> (ZFSACLInherit -> ZFSACLInherit -> ZFSACLInherit)
    -> Ord ZFSACLInherit
    ZFSACLInherit -> ZFSACLInherit -> Bool
    ZFSACLInherit -> ZFSACLInherit -> Ordering
    ZFSACLInherit -> ZFSACLInherit -> ZFSACLInherit
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    $ccompare :: ZFSACLInherit -> ZFSACLInherit -> Ordering
    compare :: ZFSACLInherit -> ZFSACLInherit -> Ordering
    $c< :: ZFSACLInherit -> ZFSACLInherit -> Bool
    < :: ZFSACLInherit -> ZFSACLInherit -> Bool
    $c<= :: ZFSACLInherit -> ZFSACLInherit -> Bool
    <= :: ZFSACLInherit -> ZFSACLInherit -> Bool
    $c> :: ZFSACLInherit -> ZFSACLInherit -> Bool
    > :: ZFSACLInherit -> ZFSACLInherit -> Bool
    $c>= :: ZFSACLInherit -> ZFSACLInherit -> Bool
    >= :: ZFSACLInherit -> ZFSACLInherit -> Bool
    $cmax :: ZFSACLInherit -> ZFSACLInherit -> ZFSACLInherit
    max :: ZFSACLInherit -> ZFSACLInherit -> ZFSACLInherit
    $cmin :: ZFSACLInherit -> ZFSACLInherit -> ZFSACLInherit
    min :: ZFSACLInherit -> ZFSACLInherit -> ZFSACLInherit
    Ord)
    instance IsString ZFSACLInherit where
    	fromString :: String -> ZFSACLInherit
    fromString String
    "discard" = ZFSACLInherit
    AIDiscard
    	fromString String
    "noallow" = ZFSACLInherit
    AINoAllow
    	fromString String
    "secure" = ZFSACLInherit
    AISecure
    	fromString String
    "passthrough" = ZFSACLInherit
    AIPassthrough
    	fromString String
    _ = String -> ZFSACLInherit
    forall a. HasCallStack => String -> a
    error String
    "Not valid aclpassthrough value"

    instance Value ZFSACLInherit where
    	toValue :: ZFSACLInherit -> String
    toValue ZFSACLInherit
    AIDiscard = String
    "discard"
    	toValue ZFSACLInherit
    AINoAllow = String
    "noallow"
    	toValue ZFSACLInherit
    AISecure = String
    "secure"
    	toValue ZFSACLInherit
    AIPassthrough = String
    "passthrough"

    data ZFSACLMode = AMDiscard | AMGroupmask | AMPassthrough deriving (Int -> ZFSACLMode -> ShowS
    [ZFSACLMode] -> ShowS
    ZFSACLMode -> String
    (Int -> ZFSACLMode -> ShowS)
    -> (ZFSACLMode -> String)
    -> ([ZFSACLMode] -> ShowS)
    -> Show ZFSACLMode
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> ZFSACLMode -> ShowS
    showsPrec :: Int -> ZFSACLMode -> ShowS
    $cshow :: ZFSACLMode -> String
    show :: ZFSACLMode -> String
    $cshowList :: [ZFSACLMode] -> ShowS
    showList :: [ZFSACLMode] -> ShowS
    Show, ZFSACLMode -> ZFSACLMode -> Bool
    (ZFSACLMode -> ZFSACLMode -> Bool)
    -> (ZFSACLMode -> ZFSACLMode -> Bool) -> Eq ZFSACLMode
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: ZFSACLMode -> ZFSACLMode -> Bool
    == :: ZFSACLMode -> ZFSACLMode -> Bool
    $c/= :: ZFSACLMode -> ZFSACLMode -> Bool
    /= :: ZFSACLMode -> ZFSACLMode -> Bool
    Eq, Eq ZFSACLMode
    Eq ZFSACLMode =>
    (ZFSACLMode -> ZFSACLMode -> Ordering)
    -> (ZFSACLMode -> ZFSACLMode -> Bool)
    -> (ZFSACLMode -> ZFSACLMode -> Bool)
    -> (ZFSACLMode -> ZFSACLMode -> Bool)
    -> (ZFSACLMode -> ZFSACLMode -> Bool)
    -> (ZFSACLMode -> ZFSACLMode -> ZFSACLMode)
    -> (ZFSACLMode -> ZFSACLMode -> ZFSACLMode)
    -> Ord ZFSACLMode
    ZFSACLMode -> ZFSACLMode -> Bool
    ZFSACLMode -> ZFSACLMode -> Ordering
    ZFSACLMode -> ZFSACLMode -> ZFSACLMode
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    $ccompare :: ZFSACLMode -> ZFSACLMode -> Ordering
    compare :: ZFSACLMode -> ZFSACLMode -> Ordering
    $c< :: ZFSACLMode -> ZFSACLMode -> Bool
    < :: ZFSACLMode -> ZFSACLMode -> Bool
    $c<= :: ZFSACLMode -> ZFSACLMode -> Bool
    <= :: ZFSACLMode -> ZFSACLMode -> Bool
    $c> :: ZFSACLMode -> ZFSACLMode -> Bool
    > :: ZFSACLMode -> ZFSACLMode -> Bool
    $c>= :: ZFSACLMode -> ZFSACLMode -> Bool
    >= :: ZFSACLMode -> ZFSACLMode -> Bool
    $cmax :: ZFSACLMode -> ZFSACLMode -> ZFSACLMode
    max :: ZFSACLMode -> ZFSACLMode -> ZFSACLMode
    $cmin :: ZFSACLMode -> ZFSACLMode -> ZFSACLMode
    min :: ZFSACLMode -> ZFSACLMode -> ZFSACLMode
    Ord)
    instance IsString ZFSACLMode where
    	fromString :: String -> ZFSACLMode
    fromString String
    "discard" = ZFSACLMode
    AMDiscard
    	fromString String
    "groupmask" = ZFSACLMode
    AMGroupmask
    	fromString String
    "passthrough" = ZFSACLMode
    AMPassthrough
    	fromString String
    _ = String -> ZFSACLMode
    forall a. HasCallStack => String -> a
    error String
    "Invalid zfsaclmode"

    instance Value ZFSACLMode where
    	toValue :: ZFSACLMode -> String
    toValue ZFSACLMode
    AMDiscard = String
    "discard"
    	toValue ZFSACLMode
    AMGroupmask = String
    "groupmask"
    	toValue ZFSACLMode
    AMPassthrough = String
    "passthrough"

    data ZFSProperty = Mounted ZFSYesNo
    	       | Mountpoint ZFSString
    	       | ReadOnly ZFSYesNo
    	       | ACLInherit ZFSACLInherit
    	       | ACLMode ZFSACLMode
    	       | StringProperty String ZFSString
    	       deriving (Int -> ZFSProperty -> ShowS
    [ZFSProperty] -> ShowS
    ZFSProperty -> String
    (Int -> ZFSProperty -> ShowS)
    -> (ZFSProperty -> String)
    -> ([ZFSProperty] -> ShowS)
    -> Show ZFSProperty
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> ZFSProperty -> ShowS
    showsPrec :: Int -> ZFSProperty -> ShowS
    $cshow :: ZFSProperty -> String
    show :: ZFSProperty -> String
    $cshowList :: [ZFSProperty] -> ShowS
    showList :: [ZFSProperty] -> ShowS
    Show, ZFSProperty -> ZFSProperty -> Bool
    (ZFSProperty -> ZFSProperty -> Bool)
    -> (ZFSProperty -> ZFSProperty -> Bool) -> Eq ZFSProperty
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: ZFSProperty -> ZFSProperty -> Bool
    == :: ZFSProperty -> ZFSProperty -> Bool
    $c/= :: ZFSProperty -> ZFSProperty -> Bool
    /= :: ZFSProperty -> ZFSProperty -> Bool
    Eq, Eq ZFSProperty
    Eq ZFSProperty =>
    (ZFSProperty -> ZFSProperty -> Ordering)
    -> (ZFSProperty -> ZFSProperty -> Bool)
    -> (ZFSProperty -> ZFSProperty -> Bool)
    -> (ZFSProperty -> ZFSProperty -> Bool)
    -> (ZFSProperty -> ZFSProperty -> Bool)
    -> (ZFSProperty -> ZFSProperty -> ZFSProperty)
    -> (ZFSProperty -> ZFSProperty -> ZFSProperty)
    -> Ord ZFSProperty
    ZFSProperty -> ZFSProperty -> Bool
    ZFSProperty -> ZFSProperty -> Ordering
    ZFSProperty -> ZFSProperty -> ZFSProperty
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    $ccompare :: ZFSProperty -> ZFSProperty -> Ordering
    compare :: ZFSProperty -> ZFSProperty -> Ordering
    $c< :: ZFSProperty -> ZFSProperty -> Bool
    < :: ZFSProperty -> ZFSProperty -> Bool
    $c<= :: ZFSProperty -> ZFSProperty -> Bool
    <= :: ZFSProperty -> ZFSProperty -> Bool
    $c> :: ZFSProperty -> ZFSProperty -> Bool
    > :: ZFSProperty -> ZFSProperty -> Bool
    $c>= :: ZFSProperty -> ZFSProperty -> Bool
    >= :: ZFSProperty -> ZFSProperty -> Bool
    $cmax :: ZFSProperty -> ZFSProperty -> ZFSProperty
    max :: ZFSProperty -> ZFSProperty -> ZFSProperty
    $cmin :: ZFSProperty -> ZFSProperty -> ZFSProperty
    min :: ZFSProperty -> ZFSProperty -> ZFSProperty
    Ord)

    toPair :: ZFSProperty -> (String, String)
    toPair :: ZFSProperty -> (String, String)
    toPair (Mounted ZFSYesNo
    v) = (String
    "mounted", ZFSYesNo -> String
    forall a. Value a => a -> String
    toValue ZFSYesNo
    v)
    toPair (Mountpoint ZFSString
    v) = (String
    "mountpoint", ZFSString -> String
    forall a. Value a => a -> String
    toValue ZFSString
    v)
    toPair (ReadOnly ZFSYesNo
    v) = (String
    "readonly", ZFSYesNo -> String
    forall a. Value a => a -> String
    toValue ZFSYesNo
    v)
    toPair (ACLInherit ZFSACLInherit
    v) = (String
    "aclinherit", ZFSACLInherit -> String
    forall a. Value a => a -> String
    toValue ZFSACLInherit
    v)
    toPair (ACLMode ZFSACLMode
    v) = (String
    "aclmode", ZFSACLMode -> String
    forall a. Value a => a -> String
    toValue ZFSACLMode
    v)
    toPair (StringProperty String
    s ZFSString
    v) = (String
    s, ZFSString -> String
    forall a. Value a => a -> String
    toValue ZFSString
    v)

    fromPair :: (String, String) -> ZFSProperty
    fromPair :: (String, String) -> ZFSProperty
    fromPair (String
    "mounted", String
    v) = ZFSYesNo -> ZFSProperty
    Mounted (String -> ZFSYesNo
    forall a. IsString a => String -> a
    fromString String
    v)
    fromPair (String
    "mountpoint", String
    v) = ZFSString -> ZFSProperty
    Mountpoint (String -> ZFSString
    forall a. IsString a => String -> a
    fromString String
    v)
    fromPair (String
    "readonly", String
    v) = ZFSYesNo -> ZFSProperty
    ReadOnly (String -> ZFSYesNo
    forall a. IsString a => String -> a
    fromString String
    v)
    fromPair (String
    "aclinherit", String
    v) = ZFSACLInherit -> ZFSProperty
    ACLInherit (String -> ZFSACLInherit
    forall a. IsString a => String -> a
    fromString String
    v)
    fromPair (String
    "aclmode", String
    v) = ZFSACLMode -> ZFSProperty
    ACLMode (String -> ZFSACLMode
    forall a. IsString a => String -> a
    fromString String
    v)
    fromPair (String
    s, String
    v) = String -> ZFSString -> ZFSProperty
    StringProperty String
    s (String -> ZFSString
    forall a. IsString a => String -> a
    fromString String
    v)