Skip to content

Next version #43

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 70 commits into from
Mar 20, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
176af66
Make Sceheme requred for non-relative URIs
garyb Jan 26, 2018
4356849
WIP
garyb Jan 29, 2018
15b8078
WIP
garyb Jan 29, 2018
df02b9e
WIP
garyb Jan 29, 2018
b843e7f
Split "nonstandard" types out
garyb Jan 29, 2018
8b316de
Record for parser/printer components
garyb Jan 29, 2018
aeae895
Free hosts from being an array
garyb Jan 29, 2018
c3decaf
Use functions for component parsing
garyb Jan 30, 2018
f528b7a
Remove some junk from Common, avoid regex parsers (mostly)
garyb Jan 30, 2018
372b3af
Style consistency for imports
garyb Jan 30, 2018
8fbf064
Delete old test for now-deleted `match1`
garyb Jan 30, 2018
14273b0
Add host/port parameters, introduce some encoded-value types
garyb Feb 1, 2018
97534e6
Introduce encoded-value type for Query
garyb Feb 1, 2018
9730451
Split up tests, update path representation
garyb Feb 3, 2018
e5e7b11
More tests, fix some re-exports
garyb Feb 5, 2018
c917296
Update to use preferred test/parse libraries
garyb Feb 5, 2018
2fed7b5
Some progress on valid handling of `,` & multi-host support
garyb Feb 6, 2018
0386d26
Fix warning
garyb Feb 6, 2018
3da1466
Fully parameterise host/port parsing
garyb Feb 6, 2018
49d3168
Safe construction for a few more values
garyb Feb 6, 2018
9a15157
Restore `QueryPairs` extra structure
garyb Feb 6, 2018
d5a5f33
Introduce `MultiHostPortPair`
garyb Feb 6, 2018
25aa142
Merge remote-tracking branch 'slamdata/master' into next
garyb Feb 6, 2018
281a512
Add extra for `user:password` handling in `UserInfo`
garyb Feb 7, 2018
33468dd
use NonEmptyString for RegName and PathSegmentNZ
safareli Feb 27, 2018
2c177fd
use crashWith for Scheme
safareli Feb 27, 2018
17c1408
add Semigroup and Monoid for Path
safareli Feb 27, 2018
3fba380
use NonEmptyString for unsafeFromString
safareli Feb 27, 2018
dcafee8
use NonEmptyString for PathSegmentNZNC
safareli Feb 27, 2018
36c51c0
update unsafe usages
safareli Feb 27, 2018
802dd78
Add crashes for illegal unsafe port/ipv4 address constructions
garyb Feb 28, 2018
4614557
Fix illegal port in tests
garyb Feb 28, 2018
619ed07
Move namespace to just URI
garyb Feb 28, 2018
308c2ee
Add details about the new setup to the README
garyb Mar 1, 2018
c6b8cec
Add doc comments for Scheme / use NES internally
garyb Mar 1, 2018
e26df37
Use NES for UserInfo internally, decouple parser composition
garyb Mar 1, 2018
c4323cc
Decouple parser composition from component parsers
garyb Mar 1, 2018
678bbbe
Clean up NES usage in UserInfo
garyb Mar 1, 2018
4d993d7
Use NonEmptyString for RegName
garyb Mar 1, 2018
56975f1
Simplify tests slightly with `nes` helper
garyb Mar 1, 2018
b11ee9a
Add fragment doc comments
garyb Mar 1, 2018
9cbc350
Add query doc comments
garyb Mar 1, 2018
df188b5
Tweak wording and add examples in UserInfo
garyb Mar 1, 2018
35d0658
Add doc comments for RegName, and print function
garyb Mar 1, 2018
b4843b0
Doc comments for IPv4Address
garyb Mar 1, 2018
a6dfbc2
Add more `Gen`s, doc comments, tests
garyb Mar 1, 2018
2d2f264
Avoid redefining some token parsers & rename some
garyb Mar 2, 2018
0015d5a
Last few doc comments for common
garyb Mar 2, 2018
daae752
Authority doc comments, remove unused synonym
garyb Mar 2, 2018
23df58e
Wording consistency tweak
garyb Mar 2, 2018
78119e5
Doc comments for HostPortPair
garyb Mar 2, 2018
98e99ad
Port doc comments
garyb Mar 2, 2018
64478e6
Tweak examples of authority option types usage
garyb Mar 2, 2018
5d81aa9
HierarchicalPart doc comments
garyb Mar 2, 2018
6316dd0
Newtype instance for UserPassInfo
safareli Mar 2, 2018
f868610
Path doc comments (and added TODO for NEA note)
garyb Mar 2, 2018
8dbdf12
Make `Path` match path-abempty from the spec
garyb Mar 2, 2018
ae42bc5
Doc comments for path varieties
garyb Mar 2, 2018
2d3a801
Adjust some segment stuff for consistency
garyb Mar 2, 2018
131b869
The -> a
garyb Mar 2, 2018
18365fd
Path segment doc comments
garyb Mar 2, 2018
d3cc178
Remove `';'` from `keyPartChar`
safareli Mar 16, 2018
4fb7a71
use in QueryPairs tests
safareli Mar 16, 2018
58a08b7
Add common URI schemes
garyb Mar 19, 2018
5dd71e8
Scheme `fromString` should fail if input is not fully consumed
garyb Mar 19, 2018
8047c1b
Make `pctEncoded` return a `NonEmptyString`
garyb Mar 19, 2018
7e612b3
More doc comment changes
garyb Mar 19, 2018
ed35231
Export char parsers used for printEncoded, etc
garyb Mar 20, 2018
a0ee260
Fix accidental loss of `try` in `URIRef` parser
garyb Mar 20, 2018
4aec4c5
Doc comments for the extras
garyb Mar 20, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
WIP
  • Loading branch information
garyb committed Jan 29, 2018
commit 4356849d04d07bb063743707ea439720172958d6
62 changes: 36 additions & 26 deletions src/Data/URI/AbsoluteURI.purs
Original file line number Diff line number Diff line change
@@ -1,74 +1,84 @@
module Data.URI.AbsoluteURI
( AbsoluteURI(..)
, parse
, parser
, print
, _scheme
, _hierPart
, _query
, module Data.URI.HierarchicalPart
, module Data.URI.Query
, module Data.URI.Scheme
) where

import Prelude

import Data.Array (catMaybes)
import Data.Either (Either)
import Data.Generic.Rep (class Generic)
import Data.Generic.Rep.Show (genericShow)
import Data.Lens (Lens', lens)
import Data.Maybe (Maybe(..))
import Data.String as S
import Data.URI.HierarchicalPart as HPart
import Data.URI.HierarchicalPart (Authority(..), HierarchicalPart(..), Host(..), Port(..), URIPath, URIPathAbs, URIPathRel, UserInfo(..), _IPv4Address, _IPv6Address, _NameAddress, _authority, _hosts, _path, _userInfo)
import Data.URI.HierarchicalPart (Authority(..), HierarchicalPart(..), Host(..), Port(..), UserInfo(..), _IPv4Address, _IPv6Address, _NameAddress, _authority, _hosts, _path, _userInfo)
import Data.URI.Query as Query
import Data.URI.Query (Query(..))
import Data.URI.Scheme as Scheme
import Data.URI.Scheme (Scheme(..))
import Text.Parsing.StringParser (ParseError, Parser, runParser)
import Text.Parsing.StringParser (Parser)
import Text.Parsing.StringParser.Combinators (optionMaybe)
import Text.Parsing.StringParser.String (eof)

-- | An absolute URI.
data AbsoluteURI = AbsoluteURI Scheme HierarchicalPart (Maybe Query)
-- | An absolute AbsoluteURI.
data AbsoluteURI userInfo path query = AbsoluteURI Scheme (HierarchicalPart userInfo path) (Maybe query)

derive instance eqAbsoluteURI ∷ Eq AbsoluteURI
derive instance ordAbsoluteURI ∷ Ord AbsoluteURI
derive instance genericAbsoluteURI ∷ Generic AbsoluteURI _
instance showAbsoluteURI ∷ Show AbsoluteURI where show = genericShow
derive instance eqAbsoluteURI ∷ (Eq userInfo, Eq path, Eq query) ⇒ Eq (AbsoluteURI userInfo path query)
derive instance ordAbsoluteURI ∷ (Ord userInfo, Ord path, Ord query) ⇒ Ord (AbsoluteURI userInfo path query)
derive instance genericAbsoluteURI ∷ Generic (AbsoluteURI userInfo path query) _
instance showAbsoluteURI ∷ (Show userInfo, Show path, Show query) ⇒ Show (AbsoluteURI userInfo path query) where show = genericShow

parse ∷ String → Either ParseError AbsoluteURI
parse = runParser parser

parser ∷ Parser AbsoluteURI
parser = AbsoluteURI
parser
∷ ∀ userInfo path query
. Parser userInfo
→ Parser path
→ Parser query
→ Parser (AbsoluteURI userInfo path query)
parser parseUserInfo parsePath parseQuery = AbsoluteURI
<$> Scheme.parser
<*> HPart.parser
<*> optionMaybe Query.parser
<*> HPart.parser parseUserInfo parsePath
<*> optionMaybe (Query.parser' parseQuery)
<* eof

print ∷ AbsoluteURI → String
print (AbsoluteURI s h q) =
print
∷ ∀ userInfo path query
. (userInfo → String)
→ (path → String)
→ (query → String)
→ AbsoluteURI userInfo path query
→ String
print printUserInfo printPath printQuery (AbsoluteURI s h q) =
S.joinWith "" $ catMaybes
[ Just (Scheme.print s)
, Just (HPart.print h)
, Query.print <$> q
, Just (HPart.print printUserInfo printPath h)
, Query.print' printQuery <$> q
]

_scheme ∷ Lens' AbsoluteURI Scheme
_scheme
∷ ∀ userInfo path query
. Lens' (AbsoluteURI userInfo path query) Scheme
_scheme =
lens
(\(AbsoluteURI s _ _) → s)
(\(AbsoluteURI _ h q) s → AbsoluteURI s h q)

_hierPart ∷ Lens' AbsoluteURI HierarchicalPart
_hierPart
∷ ∀ userInfo path query
. Lens' (AbsoluteURI userInfo path query) (HierarchicalPart userInfo path)
_hierPart =
lens
(\(AbsoluteURI _ h _) → h)
(\(AbsoluteURI s _ q) h → AbsoluteURI s h q)

_query ∷ Lens' AbsoluteURI (Maybe Query)
_query
∷ ∀ userInfo path query
. Lens' (AbsoluteURI userInfo path query) (Maybe query)
_query =
lens
(\(AbsoluteURI _ _ q) → q)
Expand Down
30 changes: 15 additions & 15 deletions src/Data/URI/Authority.purs
Original file line number Diff line number Diff line change
Expand Up @@ -30,37 +30,37 @@ import Text.Parsing.StringParser.String (string)

-- | The authority part of a URI. For example: `purescript.org`,
-- | `localhost:3000`, `user@example.net`
data Authority = Authority (Maybe UserInfo) (Array (Tuple Host (Maybe Port)))
data Authority userInfo = Authority (Maybe userInfo) (Array (Tuple Host (Maybe Port)))

derive instance eqAuthority ∷ Eq Authority
derive instance ordAuthority ∷ Ord Authority
derive instance genericAuthority ∷ Generic Authority _
instance showAuthority ∷ Show Authority where show = genericShow
derive instance eqAuthority ∷ Eq userInfo ⇒ Eq (Authority userInfo)
derive instance ordAuthority ∷ Ord userInfo ⇒ Ord (Authority userInfo)
derive instance genericAuthority ∷ Generic (Authority userInfo) _
instance showAuthority ∷ Show userInfo ⇒ Show (Authority userInfo) where show = genericShow

parser ∷ Parser Authority
parser = do
parser ∷ ∀ userInfo. Parser userInfo → Parser (Authority userInfo)
parser parseUserInfo = do
_ ← string "//"
ui ← optionMaybe $ try (UserInfo.parser <* string "@")
ui ← optionMaybe $ try (UserInfo.parser' parseUserInfo <* string "@")
hosts ← flip sepBy (string ",") $
Tuple <$> Host.parser <*> optionMaybe (string ":" *> Port.parser)
pure $ Authority ui (fromFoldable hosts)

print ∷ Authority → String
print (Authority ui hs) =
"//" <> printUserInfo <> S.joinWith "," (printHostAndPort <$> hs)
print ∷ ∀ userInfo. (userInfo → String) → Authority userInfo → String
print printUserInfo (Authority ui hs) =
"//" <> printUserInfo' ui <> S.joinWith "," (printHostAndPort <$> hs)
where
printUserInfo =
maybe "" (\u → UserInfo.print u <> "@") ui
printUserInfo' =
maybe "" (\u → printUserInfo u <> "@")
printHostAndPort (Tuple h p) =
Host.print h <> maybe "" (\n → ":" <> Port.print n) p

_userInfo ∷ Lens' Authority (Maybe UserInfo)
_userInfo ∷ ∀ userInfo. Lens' (Authority userInfo) (Maybe userInfo)
_userInfo =
lens
(\(Authority ui _) → ui)
(\(Authority _ hs) ui → Authority ui hs)

_hosts ∷ Lens' Authority (Array (Tuple Host (Maybe Port)))
_hosts ∷ ∀ userInfo. Lens' (Authority userInfo) (Array (Tuple Host (Maybe Port)))
_hosts =
lens
(\(Authority _ hs) → hs)
Expand Down
10 changes: 9 additions & 1 deletion src/Data/URI/Fragment.purs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Data.Newtype (class Newtype)
import Data.String as S
import Data.String.Regex as RX
import Data.String.Regex.Flags as RXF
import Data.URI.Common (decodePCTComponent, joinWith, parsePChar)
import Data.URI.Common (decodePCTComponent, joinWith, parsePChar, wrapParser)
import Global (encodeURIComponent)
import Partial.Unsafe (unsafePartial)
import Text.Parsing.StringParser (Parser)
Expand All @@ -26,11 +26,19 @@ derive instance genericFragment ∷ Generic Fragment _
derive instance newtypeFragment ∷ Newtype Fragment _
instance showFragment ∷ Show Fragment where show = genericShow

parser' ∷ ∀ f. Parser f → Parser f
parser' parseF = string "#" *>
wrapParser parseF (joinWith ""
<$> many (parsePChar decodePCTComponent <|> string "/" <|> string "?"))

parser ∷ Parser Fragment
parser = string "#" *>
(Fragment <<< joinWith ""
<$> many (parsePChar decodePCTComponent <|> string "/" <|> string "?"))

print' ∷ ∀ f. (f → String) → f → String
print' printF f = "#" <> printF f

print ∷ Fragment → String
print (Fragment f) =
"#" <> S.joinWith "" (map printChar $ S.split (S.Pattern "") f)
Expand Down
38 changes: 20 additions & 18 deletions src/Data/URI/HierarchicalPart.purs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ module Data.URI.HierarchicalPart
, _authority
, _path
, module Data.URI.Authority
, module Data.URI.Path
) where

import Prelude
Expand All @@ -19,44 +18,47 @@ import Data.Maybe (Maybe(..))
import Data.String as S
import Data.URI.Authority (Authority(..), Host(..), Port(..), UserInfo(..), _IPv4Address, _IPv6Address, _NameAddress, _hosts, _userInfo)
import Data.URI.Authority as Authority
import Data.URI.Path (URIPath, URIPathAbs, URIPathRel)
import Data.URI.Path as Path
import Text.Parsing.StringParser (Parser)

-- | The "hierarchical part" of a generic or absolute URI.
data HierarchicalPart = HierarchicalPart (Maybe Authority) (Maybe URIPathAbs)
data HierarchicalPart userInfo path = HierarchicalPart (Maybe (Authority userInfo)) (Maybe path)

derive instance eqHierarchicalPart ∷ Eq HierarchicalPart
derive instance ordHierarchicalPart ∷ Ord HierarchicalPart
derive instance genericHierarchicalPart ∷ Generic HierarchicalPart _
instance showHierarchicalPart ∷ Show HierarchicalPart where show = genericShow
derive instance eqHierarchicalPart ∷ (Eq userInfo, Eq path) ⇒ Eq (HierarchicalPart userInfo path)
derive instance ordHierarchicalPart ∷ (Ord userInfo, Ord path) ⇒ Ord (HierarchicalPart userInfo path)
derive instance genericHierarchicalPart ∷ Generic (HierarchicalPart userInfo path) _
instance showHierarchicalPart ∷ (Show userInfo, Show path) ⇒ Show (HierarchicalPart userInfo path) where show = genericShow

parser ∷ Parser HierarchicalPart
parser = withAuth <|> withoutAuth
parser ∷ ∀ userInfo path. Parser userInfo → Parser path → Parser (HierarchicalPart userInfo path)
parser parseUserInfo parsePath = withAuth <|> withoutAuth
where
withAuth =
HierarchicalPart <<< Just
<$> Authority.parser
<*> Path.parsePathAbEmpty Path.parseURIPathAbs
<$> Authority.parser parseUserInfo
<*> Path.parsePathAbEmpty parsePath

withoutAuth = HierarchicalPart Nothing <$> noAuthPath

noAuthPath
= (Just <$> Path.parsePathAbsolute Path.parseURIPathAbs)
<|> (Just <$> Path.parsePathRootless Path.parseURIPathAbs)
= (Just <$> Path.parsePathAbsolute parsePath)
<|> (Just <$> Path.parsePathRootless parsePath)
<|> pure Nothing

print ∷ HierarchicalPart → String
print (HierarchicalPart a p) =
S.joinWith "" (catMaybes [Authority.print <$> a, Path.printPath <$> p])
print ∷ ∀ userInfo path. (userInfo → String) → (path → String) → HierarchicalPart userInfo path → String
print printUserInfo printPath (HierarchicalPart a p) =
S.joinWith "" $
catMaybes
[ Authority.print printUserInfo <$> a
, printPath <$> p
]

_authority ∷ Lens' HierarchicalPart (Maybe Authority)
_authority ∷ ∀ userInfo path. Lens' (HierarchicalPart userInfo path) (Maybe (Authority userInfo))
_authority =
lens
(\(HierarchicalPart a _) → a)
(\(HierarchicalPart _ p) a → HierarchicalPart a p)

_path ∷ Lens' HierarchicalPart (Maybe URIPathAbs)
_path ∷ ∀ userInfo path. Lens' (HierarchicalPart userInfo path) (Maybe path)
_path =
lens
(\(HierarchicalPart _ p) → p)
Expand Down
13 changes: 7 additions & 6 deletions src/Data/URI/Path.purs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ import Data.String as Str
import Data.URI.Common (PCTEncoded, decodePCT, joinWith, parsePCTEncoded, parsePChar, parseSubDelims, parseUnreserved, wrapParser)
import Global (encodeURI)
import Text.Parsing.StringParser (Parser(..), ParseError(..), try)
import Text.Parsing.StringParser.Combinators (many, many1)
import Text.Parsing.StringParser.Combinators (many, many1, optionMaybe)
import Text.Parsing.StringParser.String (string)
import Debug.Trace

-- | A general URI path, can be used to represent relative or absolute paths
-- | that are sandboxed or unsandboxed.
Expand All @@ -47,14 +48,14 @@ parsePath p
<|> pure Nothing

parsePathAbEmpty ∷ ∀ p. Parser p → Parser (Maybe p)
parsePathAbEmpty p
= try (Just <$> wrapParser p
(joinWith "" <$> many (append <$> string "/" <*> parseSegment)))
<|> pure Nothing
parsePathAbEmpty p =
optionMaybe $ wrapParser p do
parts ← many1 (string "/" *> parseSegment)
pure ("/" <> joinWith "/" parts)

parsePathAbsolute ∷ ∀ p. Parser p → Parser p
parsePathAbsolute p = wrapParser p $ do
_ <- string "/"
_ string "/"
start ← parseSegmentNonZero
rest ← joinWith "" <$> many (append <$> string "/" <*> parseSegment)
pure $ "/" <> start <> rest
Expand Down
8 changes: 8 additions & 0 deletions src/Data/URI/Query.purs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
module Data.URI.Query
( Query(..)
, parser
, parser'
, print
, print'
) where

import Prelude
Expand Down Expand Up @@ -36,6 +38,9 @@ instance showQuery ∷ Show Query where show = genericShow
derive newtype instance semigroupQuery ∷ Semigroup Query
derive newtype instance monoidQuery ∷ Monoid Query

parser' ∷ ∀ q. Parser q → Parser q
parser' parseQ = string "?" *> (wrapParser parseQ (try (rxPat "[^#]*")))

parser ∷ Parser Query
parser = string "?" *> (Query <$> wrapParser parseParts (try (rxPat "[^#]*")))

Expand All @@ -48,6 +53,9 @@ parsePart = do
value ← optionMaybe $ decodeURIComponent <$> (string "=" *> rxPat "[^;&]*")
pure $ Tuple key value

print' ∷ ∀ q. (q → String) → q → String
print' printQ q = "?" <> printQ q

print ∷ Query → String
print (Query m) =
case m of
Expand Down
Loading