packages feed

document-build-0.2.0.0: src/Document/Build/OutputFile.hs

{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeOperators #-}
{-# OPTIONS_GHC -Wall #-}

{- | A file of the output tree of a build.

A 'OutputFile' is a product: its fields are named 'outputPath', 'outputSha256', 'outputGitDetails', 'outputPages' and 'outputImageInfo'.
-}
module Document.Build.OutputFile (
  -- * Type
  OutputFile (..),

  -- * Optics
  OutputFileLike (..),
  lawNamesOutputFile,
  InheritOutputFile,
  inheritOutputFile,
) where

import Control.DeepSeq (NFData)
import Control.Lens (Optic, cloneLens, view)
import Data.Aeson (FromJSON (..), ToJSON (..), object, withObject, (.:), (.:?), (.=))
import Data.Data (Data)
import Data.Functor.Const (Const)
import Document.Build.GitDetails (GitDetails)
import Document.Build.ImageInfo (ImageInfo)
import Document.Build.Name.OutputGitDetails (OutputGitDetailsLike (..))
import Document.Build.Name.OutputImageInfo (OutputImageInfoLike (..))
import Document.Build.Name.OutputPages (OutputPagesLike (..))
import Document.Build.Name.OutputPath (OutputPathLike (..))
import Document.Build.Name.OutputSha256 (OutputSha256Like (..))
import GHC.Generics (Generic)

{- | An output file: its path ('outputPath'), its SHA-256 hash
('outputSha256'), the git details of the source file at the root of its tree
('outputGitDetails'), its number of pages if it is a PDF file
('outputPages'), and information about it if it is an image
('outputImageInfo').

@since 0.1.0.0
-}
data OutputFile
  = OutputFile FilePath String (Maybe GitDetails) (Maybe Int) (Maybe ImageInfo)
  deriving stock (Eq, Ord, Show, Generic, Data)
  deriving anyclass (NFData)

-- | @since 0.1.0.0
instance ToJSON OutputFile where
  toJSON (OutputFile p h g n i) =
    object ["path" .= p, "sha256" .= h, "git" .= g, "pages" .= n, "image" .= i]

-- | @since 0.1.0.0
instance FromJSON OutputFile where
  parseJSON =
    withObject "OutputFile" $ \o ->
      OutputFile <$> o .: "path" <*> o .: "sha256" <*> o .:? "git" <*> o .:? "pages" <*> o .:? "image"

{- | The class of 'OutputFile'.

@since 0.2.0.0
-}
class OutputFileLike p f x x' where
  outputFile ::
    Optic p f x x' OutputFile OutputFile

{- | Identity

@since 0.2.0.0
-}
instance (x' ~ OutputFile) => OutputFileLike p f OutputFile x' where
  outputFile =
    id
  {-# INLINE outputFile #-}

{- | Lens

@since 0.2.0.0
-}
instance (p ~ (->), Functor f, x' ~ OutputFile) => OutputPathLike p f OutputFile x' where
  outputPath f (OutputFile x1 x2 x3 x4 x5) =
    fmap (\x1' -> OutputFile x1' x2 x3 x4 x5) (f x1)
  {-# INLINE outputPath #-}

{- | Lens

@since 0.2.0.0
-}
instance (p ~ (->), Functor f, x' ~ OutputFile) => OutputSha256Like p f OutputFile x' where
  outputSha256 f (OutputFile x1 x2 x3 x4 x5) =
    fmap (\x2' -> OutputFile x1 x2' x3 x4 x5) (f x2)
  {-# INLINE outputSha256 #-}

{- | Lens

@since 0.2.0.0
-}
instance (p ~ (->), Functor f, x' ~ OutputFile) => OutputGitDetailsLike p f OutputFile x' where
  outputGitDetails f (OutputFile x1 x2 x3 x4 x5) =
    fmap (\x3' -> OutputFile x1 x2 x3' x4 x5) (f x3)
  {-# INLINE outputGitDetails #-}

{- | Lens

@since 0.2.0.0
-}
instance (p ~ (->), Functor f, x' ~ OutputFile) => OutputPagesLike p f OutputFile x' where
  outputPages f (OutputFile x1 x2 x3 x4 x5) =
    fmap (\x4' -> OutputFile x1 x2 x3 x4' x5) (f x4)
  {-# INLINE outputPages #-}

{- | Lens

@since 0.2.0.0
-}
instance (p ~ (->), Functor f, x' ~ OutputFile) => OutputImageInfoLike p f OutputFile x' where
  outputImageInfo f (OutputFile x1 x2 x3 x4 x5) =
    fmap (OutputFile x1 x2 x3 x4) (f x5)
  {-# INLINE outputImageInfo #-}

{- | Rebuild a value using only the name of each field.

Laws:

> lawNamesOutputFile == id

@since 0.2.0.0
-}
lawNamesOutputFile :: OutputFile -> OutputFile
lawNamesOutputFile s =
  OutputFile
    (view (cloneLens outputPath) s)
    (view (cloneLens outputSha256) s)
    (view (cloneLens outputGitDetails) s)
    (view (cloneLens outputPages) s)
    (view (cloneLens outputImageInfo) s)

{- | The classes that a data type holding 'OutputFile' inherits.

@since 0.2.0.0
-}
type InheritOutputFile s =
  ( OutputFileLike (->) (Const ()) s s
  , OutputPathLike (->) (Const ()) s s
  , OutputSha256Like (->) (Const ()) s s
  , OutputGitDetailsLike (->) (Const ()) s s
  , OutputPagesLike (->) (Const ()) s s
  , OutputImageInfoLike (->) (Const ()) s s
  )

{- | Check, where it is applied, that @s@ inherits every name of 'OutputFile'.

@since 0.2.0.0
-}
inheritOutputFile :: (InheritOutputFile s) => proxy s -> ()
inheritOutputFile _ =
  ()