content: module Text.ProtocolBuffers.ProtoCompile.Instances(showsType,parseType,showsLabel,parseLabel) where
  
  import Text.ParserCombinators.ReadP
  import Text.DescriptorProtos.FieldDescriptorProto.Type(Type(..))
  import Text.DescriptorProtos.FieldDescriptorProto.Label(Label(..))
  
  {-
  instance Show Type where
    showsPrec _ = showsType
  
  instance Read Type where
    readsPrec _ = readP_to_S readType
  -}
  
  showsLabel :: Label -> ShowS
  showsLabel LABEL_OPTIONAL s = "optional" ++ s
  showsLabel LABEL_REQUIRED s = "required" ++ s
  showsLabel LABEL_REPEATED s = "repeated" ++ s
  
  showsType :: Type -> ShowS
  showsType TYPE_DOUBLE s = "double" ++ s
  showsType TYPE_FLOAT s = "float" ++ s
  showsType TYPE_INT64 s = "int64" ++ s
  showsType TYPE_UINT64 s = "uint64" ++ s
  showsType TYPE_INT32  s = "int32" ++ s
  showsType TYPE_FIXED64 s = "fixed64" ++ s
  showsType TYPE_FIXED32 s = "fixed32" ++ s
  showsType TYPE_BOOL s = "bool" ++ s
  showsType TYPE_STRING s = "string" ++ s
  showsType TYPE_GROUP s = "group" ++ s
  showsType TYPE_MESSAGE s = "message" ++ s
  showsType TYPE_BYTES s = "bytes" ++ s
  showsType TYPE_UINT32 s = "uint32" ++ s
  showsType TYPE_ENUM s = "enum" ++ s
  showsType TYPE_SFIXED32 s = "sfixed32" ++ s
  showsType TYPE_SFIXED64 s = "sfixed64" ++ s
  showsType TYPE_SINT32 s = "sint32" ++ s
  showsType TYPE_SINT64 s = "sint64" ++ s
  
  -- | parseType returns Nothing when the String is user-defined.  This means it could be either a
  -- Message or an Enum or a syntax error. The Nothing return is fixed up in
  -- Text.ProtocolBuffers.ProtoCompile.Resolve.fqField
  parseType :: String -> Maybe Type
  parseType s = case readP_to_S readType s of
                  [(val,[])] -> Just val
                  _ -> Nothing
  
  -- | parseLabel recognizes optional, required, and repeated.  All other strings result in Nothing
  parseLabel :: String -> Maybe Label
  parseLabel s = case readP_to_S readLabel s of
                  [(val,[])] -> Just val
                  _ -> Nothing
  
  readLabel :: ReadP Label
  readLabel = choice [ return LABEL_OPTIONAL << string "optional"
                     , return LABEL_REQUIRED << string "required"
                     , return LABEL_REPEATED << string "repeated"
                     ]
  
  -- readType interprets the string in the proto file, but there is no way to know if an unknown
  -- string refers to a Message or to an Enum
  readType :: ReadP Type
  readType = choice [ return TYPE_DOUBLE << string "double"
                    , return TYPE_FLOAT << string "float"
                    , return TYPE_INT64 << string "int64"
                    , return TYPE_UINT64 << string "uint64"
                    , return TYPE_INT32  << string "int32"
                    , return TYPE_FIXED64 << string "fixed64"
                    , return TYPE_FIXED32 << string "fixed32"
                    , return TYPE_BOOL << string "bool"
                    , return TYPE_STRING << string "string"
                    , return TYPE_GROUP << string "group"
                    , return TYPE_BYTES << string "bytes"
                    , return TYPE_UINT32 << string "uint32"
                    , return TYPE_SFIXED32 << string "sfixed32"
                    , return TYPE_SFIXED64 << string "sfixed64"
                    , return TYPE_SINT32 << string "sint32"
                    , return TYPE_SINT64 << string "sint64"
                    ]
  --                , return TYPE_MESSAGE << string "..."
  --                , return TYPE_ENUM << string "..."
  
  (<<) :: Monad m => m a -> m b -> m a
  (<<) = flip (>>)
  
  