Movatterモバイル変換


[0]ホーム

URL:


modulePostgreSQL.Binary.Decoder(Decoder,run,-- * Primitiveint,float4,float8,bool,bytea_strict,bytea_lazy,-- * Textualtext_strict,text_lazy,char,-- * Miscfn,numeric,uuid,json_ast,json_bytes,jsonb_ast,jsonb_bytes,-- * Timedate,time_int,time_float,timetz_int,timetz_float,timestamp_int,timestamp_float,timestamptz_int,timestamptz_float,interval_int,interval_float,-- * Exotic-- ** ArrayArrayDecoder,array,arrayDimension,arrayValue,arrayNonNullValue,-- ** CompositeCompositeDecoder,composite,compositeValue,compositeNonNullValue,-- ** HStorehstore,-- **enum,)whereimportPostgreSQL.Binary.Preludehiding(take,bool,drop,state,fail,failure)importBinaryParserimportqualifiedPostgreSQL.Binary.DataasDataimportqualifiedPostgreSQL.Binary.IntegralasIntegralimportqualifiedPostgreSQL.Binary.IntervalasIntervalimportqualifiedPostgreSQL.Binary.NumericasNumericimportqualifiedPostgreSQL.Binary.TimeasTimeimportqualifiedData.VectorasVectorimportqualifiedData.ByteStringasByteStringimportqualifiedData.ByteString.LazyasLazyByteStringimportqualifiedData.TextasTextimportqualifiedData.Text.EncodingasTextimportqualifiedData.Text.Encoding.ErrorasTextimportqualifiedData.Text.Lazy.EncodingasLazyTextimportqualifiedData.UUIDasUUIDimportqualifiedData.AesonasAesontypeDecoder=BinaryParser-- * Helpers--------------------------- |-- Any int number of a limited byte-size.{-# INLINE intOfSize #-}intOfSize::(Integrala,Bitsa)=>Int->DecoderaintOfSizex=fmapIntegral.pack(bytesOfSizex){-# INLINABLE onContent #-}onContent::Decodera->Decoder(Maybea)onContentdecoder=intOfSize4>>=\case(-1)->pureNothingn->fmapJust(sizedndecoder){-# INLINABLE content #-}content::Decoder(MaybeByteString)content=intOfSize4>>=\case(-1)->pureNothingn->fmapJust(bytesOfSizen){-# INLINE nonNull #-}nonNull::Maybea->DecoderanonNull=maybe(failure"Unexpected NULL")return-- * Primitive--------------------------- |-- Lifts a custom decoder implementation.{-# INLINE fn #-}fn::(ByteString->EitherTexta)->Decoderafnfn=BinaryParser.remainders>>=eitherBinaryParser.failurereturn.fn{-# INLINE int #-}int::(Integrala,Bitsa)=>Decoderaint=fmapIntegral.packremaindersfloat4::DecoderFloatfloat4=unsafeCoerce(int::DecoderInt32)float8::DecoderDoublefloat8=unsafeCoerce(int::DecoderInt64){-# INLINE bool #-}bool::DecoderBoolbool=fmap(==1)byte{-# NOINLINE numeric #-}numeric::DecoderScientificnumeric=docomponentsAmount<-intOfSize2pointIndex<-intOfSize2signCode<-intOfSize2unitOfSize2components<-Vector.replicateMcomponentsAmount(intOfSize2)eitherfailurereturn(Numeric.scientificpointIndexsignCodecomponents){-# INLINABLE uuid #-}uuid::DecoderUUIDuuid=UUID.fromWords<$>intOfSize4<*>intOfSize4<*>intOfSize4<*>intOfSize4{-# INLINABLE json_ast #-}json_ast::DecoderAeson.Valuejson_ast=bytea_strict>>=either(BinaryParser.failure.fromString)pure.Aeson.eitherDecodeStrict'-- |-- Given a function, which parses a plain UTF-8 JSON string encoded as a byte-array,-- produces a decoder.{-# INLINABLE json_bytes #-}json_bytes::(ByteString->EitherTexta)->Decoderajson_bytescont=getAllBytes>>=parseJSONwheregetAllBytes=BinaryParser.remaindersparseJSON=eitherBinaryParser.failurereturn.cont{-# INLINABLE jsonb_ast #-}jsonb_ast::DecoderAeson.Valuejsonb_ast=jsonb_bytes$mapLeftfromString.Aeson.eitherDecodeStrict'-- |-- Given a function, which parses a plain UTF-8 JSON string encoded as a byte-array,-- produces a decoder.---- For those wondering, yes,-- JSONB is encoded as plain JSON string in the binary format of Postgres.-- Sad, but true.{-# INLINABLE jsonb_bytes #-}jsonb_bytes::(ByteString->EitherTexta)->Decoderajsonb_bytescont=getAllBytes>>=trimBytes>>=parseJSONwheregetAllBytes=BinaryParser.remainderstrimBytes=maybe(BinaryParser.failure"Empty input")return.fmapsnd.ByteString.unconsparseJSON=eitherBinaryParser.failurereturn.cont-- ** Textual--------------------------- |-- A UTF-8-decoded char.{-# INLINABLE char #-}char::DecoderCharchar=fmapText.unconstext_strict>>=\caseJust(c,"")->returncNothing->failure"Empty input"_->failure"Consumed too much"-- |-- Any of the variable-length character types:-- BPCHAR, VARCHAR, NAME and TEXT.{-# INLINABLE text_strict #-}text_strict::DecoderTexttext_strict=remainders>>=either(failure.exception)return.Text.decodeUtf8'whereexception=\caseText.DecodeErrormessagebyte->fromStringmessage_->$bug"Unexpected unicode exception"-- |-- Any of the variable-length character types:-- BPCHAR, VARCHAR, NAME and TEXT.{-# INLINABLE text_lazy #-}text_lazy::DecoderLazyTexttext_lazy=bytea_lazy>>=either(failure.exception)return.LazyText.decodeUtf8'whereexception=\caseText.DecodeErrormessagebyte->fromStringmessage_->$bug"Unexpected unicode exception"-- |-- BYTEA or any other type in its undecoded form.{-# INLINE bytea_strict #-}bytea_strict::DecoderByteStringbytea_strict=remainders-- |-- BYTEA or any other type in its undecoded form.{-# INLINE bytea_lazy #-}bytea_lazy::DecoderLazyByteStringbytea_lazy=fmapLazyByteString.fromStrictremainders-- * Date and Time--------------------------- |-- @DATE@ values decoding.date::DecoderDaydate=fmap(Time.postgresJulianToDay.fromIntegral)(int::DecoderInt32)-- |-- @TIME@ values decoding for servers, which have @integer_datetimes@ enabled.time_int::DecoderTimeOfDaytime_int=fmapTime.microsToTimeOfDayint-- |-- @TIME@ values decoding for servers, which don't have @integer_datetimes@ enabled.time_float::DecoderTimeOfDaytime_float=fmapTime.secsToTimeOfDayfloat8-- |-- @TIMETZ@ values decoding for servers, which have @integer_datetimes@ enabled.timetz_int::Decoder(TimeOfDay,TimeZone)timetz_int=(,)<$>sized8time_int<*>tz-- |-- @TIMETZ@ values decoding for servers, which don't have @integer_datetimes@ enabled.timetz_float::Decoder(TimeOfDay,TimeZone)timetz_float=(,)<$>sized8time_float<*>tz{-# INLINE tz #-}tz::DecoderTimeZonetz=fmap(minutesToTimeZone.negate.(flipdiv60).fromIntegral)(int::DecoderInt32)-- |-- @TIMESTAMP@ values decoding for servers, which have @integer_datetimes@ enabled.timestamp_int::DecoderLocalTimetimestamp_int=fmapTime.microsToLocalTimeint-- |-- @TIMESTAMP@ values decoding for servers, which don't have @integer_datetimes@ enabled.timestamp_float::DecoderLocalTimetimestamp_float=fmapTime.secsToLocalTimefloat8-- |-- @TIMESTAMP@ values decoding for servers, which have @integer_datetimes@ enabled.timestamptz_int::DecoderUTCTimetimestamptz_int=fmapTime.microsToUTCint-- |-- @TIMESTAMP@ values decoding for servers, which don't have @integer_datetimes@ enabled.timestamptz_float::DecoderUTCTimetimestamptz_float=fmapTime.secsToUTCfloat8-- |-- @INTERVAL@ values decoding for servers, which don't have @integer_datetimes@ enabled.interval_int::DecoderDiffTimeinterval_int=dou<-sized8intd<-sized4intm<-intreturn$Interval.toDiffTime$Interval.Intervaludm-- |-- @INTERVAL@ values decoding for servers, which have @integer_datetimes@ enabled.interval_float::DecoderDiffTimeinterval_float=dou<-sized8(fmap(round.(*(10^6)).toRational)float8)d<-sized4intm<-intreturn$Interval.toDiffTime$Interval.Intervaludm-- * Exotic--------------------------- |-- A lower-level array data parser,-- which aggregates the intermediate data representation as per the Postgres format.---- Only use this if 'array' doesn't fit your case.{-# INLINABLE arrayRep #-}arrayRep::DecoderData.ArrayarrayRep=dodimensionsAmount<-intOfSize4nullsValue<-nullsoid<-intOfSize4dimensions<-Vector.replicateMdimensionsAmountdimensionletvaluesAmount=(Vector.product.Vector.mapfst)dimensionsvalues<-Vector.replicateM(fromIntegralvaluesAmount)contentreturn(dimensions,values,nullsValue,oid)wheredimension=(,)<$>intOfSize4<*>intOfSize4nulls=intOfSize4>>=\(x::Word32)->casexof0->returnFalse1->returnTruew->failure$"Invalid value: "<>(fromString.show)w{-# INLINABLE compositeRep #-}compositeRep::DecoderData.CompositecompositeRep=docomponentsAmount<-intOfSize4Vector.replicateMcomponentsAmountcomponentwherecomponent=(,)<$>intOfSize4<*>content-- |-- A function for generic in place parsing of an HStore value.---- Accepts:---- * An implementation of the @replicateM@ function-- (@Control.Monad.'Control.Monad.replicateM'@, @Data.Vector.'Data.Vector.replicateM'@),-- which determines how to produce the final datastructure from the rows.---- * A decoder for keys.---- * A decoder for values.---- Here's how you can use it to produce a parser to list:---- @-- hstoreAsList :: Decoder [ ( Text , Maybe Text ) ]-- hstoreAsList =--   hstore replicateM text text-- @--{-# INLINABLE hstore #-}hstore::(forallm.Monadm=>Int->m(k,Maybev)->mr)->Decoderk->Decoderv->DecoderrhstorereplicateMkeyContentvalueContent=docomponentsAmount<-intOfSize4replicateMcomponentsAmountcomponentwherecomponent=(,)<$>key<*>valuewherekey=onContentkeyContent>>=nonNullvalue=onContentvalueContent{-# INLINABLE hstoreRep #-}hstoreRep::DecoderData.HStorehstoreRep=docomponentsAmount<-intOfSize4Vector.replicateMcomponentsAmountcomponentwherecomponent=(,)<$>key<*>contentwherekey=intOfSize4>>=bytesOfSize-- * Composite-------------------------newtypeCompositeDecodera=CompositeDecoder(Decodera)deriving(Functor,Applicative,Monad)-- |-- Unlift a 'CompositeDecoder' to a value 'Decoder'.{-# INLINE composite #-}composite::CompositeDecodera->Decoderacomposite(CompositeDecoderdecoder)=unitOfSize4*>decoder-- |-- Lift a value 'Decoder' into 'CompositeDecoder'.{-# INLINE compositeValue #-}compositeValue::Decodera->CompositeDecoder(Maybea)compositeValue=CompositeDecoder.onContent-- |-- Lift a non-nullable value 'Decoder' into 'CompositeDecoder'.{-# INLINE compositeNonNullValue #-}compositeNonNullValue::Decodera->CompositeDecoderacompositeNonNullValue=CompositeDecoder.join.fmap(maybe(failure"Unexpected NULL")return).onContent-- * Array--------------------------- |-- An efficient generic array decoder,-- which constructs the result value in place while parsing.---- Here's how you can use it to produce a specific array value decoder:---- @-- x :: Decoder [ [ Text ] ]-- x =--   array (arrayDimension replicateM (fmap catMaybes (arrayDimension replicateM (arrayValue text))))-- @--newtypeArrayDecodera=ArrayDecoder([Word32]->Decodera)deriving(Functor)-- |-- Unlift an 'ArrayDecoder' to a value 'Decoder'.{-# INLINE array #-}array::ArrayDecodera->Decoderaarray(ArrayDecoderdecoder)=dodimensionsAmount<-intOfSize4unitOfSize(4+4)dimensionSizes<-replicateMdimensionsAmountdimensionSizedecoderdimensionSizeswheredimensionSize=intOfSize4<*unitOfSize4-- |-- A function for parsing a dimension of an array.-- Provides support for multi-dimensional arrays.---- Accepts:---- * An implementation of the @replicateM@ function-- (@Control.Monad.'Control.Monad.replicateM'@, @Data.Vector.'Data.Vector.replicateM'@),-- which determines the output value.---- * A decoder of its components, which can be either another 'arrayDimension' or 'arrayValue'.--{-# INLINE arrayDimension #-}arrayDimension::(forallm.Monadm=>Int->ma->mb)->ArrayDecodera->ArrayDecoderbarrayDimensionreplicateM(ArrayDecodercomponent)=ArrayDecoder$\casehead:tail->replicateM(fromIntegralhead)(componenttail)_->failure"A missing dimension length"-- |-- Lift a value 'Decoder' into 'ArrayDecoder' for parsing of nullable leaf values.{-# INLINE arrayValue #-}arrayValue::Decodera->ArrayDecoder(Maybea)arrayValue=ArrayDecoder.const.onContent-- |-- Lift a value 'Decoder' into 'ArrayDecoder' for parsing of non-nullable leaf values.{-# INLINE arrayNonNullValue #-}arrayNonNullValue::Decodera->ArrayDecoderaarrayNonNullValue=ArrayDecoder.const.join.fmap(maybe(failure"Unexpected NULL")return).onContent-- * Enum--------------------------- |-- Given a partial mapping from text to value,-- produces a decoder of that value.{-# INLINE enum #-}enum::(Text->Maybea)->Decoderaenummapping=text_strict>>=onTextwhereonTexttext=maybeonNothingonJust(mappingtext)whereonNothing=failure("No mapping for text \""<>text<>"\"")onJust=pure

[8]ページ先頭

©2009-2025 Movatter.jp