diff --git a/ip_addr.go b/ip_addr.go new file mode 100644 index 0000000..ebf553d --- /dev/null +++ b/ip_addr.go @@ -0,0 +1,49 @@ +// Copyright 2022 Walter Scheper +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +package rapid + +import ( + "fmt" + "net/netip" +) + +const ( + ipv4Len = 4 + ipv6Len = 16 +) + +type ipGen struct { + ipv6 bool +} + +func (g *ipGen) String() string { + return fmt.Sprintf("IP(ipv6=%v)", g.ipv6) +} + +func (g *ipGen) value(t *T) netip.Addr { + var b []byte + if g.ipv6 { + b = SliceOfN(Byte(), ipv6Len, ipv6Len).Draw(t, g.String()) + } else { + b = SliceOfN(Byte(), ipv4Len, ipv4Len).Draw(t, g.String()) + } + + addr, _ := netip.AddrFromSlice(b) + return addr +} + +func IPv4() *Generator[netip.Addr] { + return newGenerator[netip.Addr](&ipGen{ + ipv6: false, + }) +} + +func IPv6() *Generator[netip.Addr] { + return newGenerator[netip.Addr](&ipGen{ + ipv6: true, + }) +} diff --git a/ip_addr_example_test.go b/ip_addr_example_test.go new file mode 100644 index 0000000..8839d42 --- /dev/null +++ b/ip_addr_example_test.go @@ -0,0 +1,45 @@ +// Copyright 2020 Walter Scheper +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +package rapid_test + +import ( + "fmt" + + "pgregory.net/rapid" +) + +func ExampleIPv4() { + gen := rapid.IPv4() + + for i := 0; i < 5; i++ { + addr := gen.Example(i) + fmt.Println(addr.String()) + } + + // Output: + // 0.23.24.7 + // 100.146.0.0 + // 0.222.65.1 + // 1.49.104.14 + // 11.56.0.83 +} + +func ExampleIPv6() { + gen := rapid.IPv6() + + for i := 0; i < 5; i++ { + addr := gen.Example(i) + fmt.Println(addr.String()) + } + + // Output: + // 17:1807:e2c4:8210:7202:f4b2:a0e2:8dc + // 6492:0:fa37:b00:b5c3:4e6:6a01:c802 + // de:4101:9f5:3:104:5dc:b600:905 + // 131:680e:97ff:d200:ae1:4d00:2300:103 + // b38:53:ff07:200:8c28:ee:ad00:1b +} diff --git a/tld.go b/tld.go new file mode 100644 index 0000000..d3774ea --- /dev/null +++ b/tld.go @@ -0,0 +1,1503 @@ +// Copyright 2020 Walter Scheper +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +package rapid + +import "strings" + +// sourced from https://data.iana.org/TLD/tlds-alpha-by-domain.txt +// Version 2022092400, Last Updated Sun Sep 25 02:07:59 UTC 2022 +const tldsByAlpha = ` +AAA +AARP +ABARTH +ABB +ABBOTT +ABBVIE +ABC +ABLE +ABOGADO +ABUDHABI +AC +ACADEMY +ACCENTURE +ACCOUNTANT +ACCOUNTANTS +ACO +ACTOR +AD +ADAC +ADS +ADULT +AE +AEG +AERO +AETNA +AF +AFL +AFRICA +AG +AGAKHAN +AGENCY +AI +AIG +AIRBUS +AIRFORCE +AIRTEL +AKDN +AL +ALFAROMEO +ALIBABA +ALIPAY +ALLFINANZ +ALLSTATE +ALLY +ALSACE +ALSTOM +AM +AMAZON +AMERICANEXPRESS +AMERICANFAMILY +AMEX +AMFAM +AMICA +AMSTERDAM +ANALYTICS +ANDROID +ANQUAN +ANZ +AO +AOL +APARTMENTS +APP +APPLE +AQ +AQUARELLE +AR +ARAB +ARAMCO +ARCHI +ARMY +ARPA +ART +ARTE +AS +ASDA +ASIA +ASSOCIATES +AT +ATHLETA +ATTORNEY +AU +AUCTION +AUDI +AUDIBLE +AUDIO +AUSPOST +AUTHOR +AUTO +AUTOS +AVIANCA +AW +AWS +AX +AXA +AZ +AZURE +BA +BABY +BAIDU +BANAMEX +BANANAREPUBLIC +BAND +BANK +BAR +BARCELONA +BARCLAYCARD +BARCLAYS +BAREFOOT +BARGAINS +BASEBALL +BASKETBALL +BAUHAUS +BAYERN +BB +BBC +BBT +BBVA +BCG +BCN +BD +BE +BEATS +BEAUTY +BEER +BENTLEY +BERLIN +BEST +BESTBUY +BET +BF +BG +BH +BHARTI +BI +BIBLE +BID +BIKE +BING +BINGO +BIO +BIZ +BJ +BLACK +BLACKFRIDAY +BLOCKBUSTER +BLOG +BLOOMBERG +BLUE +BM +BMS +BMW +BN +BNPPARIBAS +BO +BOATS +BOEHRINGER +BOFA +BOM +BOND +BOO +BOOK +BOOKING +BOSCH +BOSTIK +BOSTON +BOT +BOUTIQUE +BOX +BR +BRADESCO +BRIDGESTONE +BROADWAY +BROKER +BROTHER +BRUSSELS +BS +BT +BUGATTI +BUILD +BUILDERS +BUSINESS +BUY +BUZZ +BV +BW +BY +BZ +BZH +CA +CAB +CAFE +CAL +CALL +CALVINKLEIN +CAM +CAMERA +CAMP +CANCERRESEARCH +CANON +CAPETOWN +CAPITAL +CAPITALONE +CAR +CARAVAN +CARDS +CARE +CAREER +CAREERS +CARS +CASA +CASE +CASH +CASINO +CAT +CATERING +CATHOLIC +CBA +CBN +CBRE +CBS +CC +CD +CENTER +CEO +CERN +CF +CFA +CFD +CG +CH +CHANEL +CHANNEL +CHARITY +CHASE +CHAT +CHEAP +CHINTAI +CHRISTMAS +CHROME +CHURCH +CI +CIPRIANI +CIRCLE +CISCO +CITADEL +CITI +CITIC +CITY +CITYEATS +CK +CL +CLAIMS +CLEANING +CLICK +CLINIC +CLINIQUE +CLOTHING +CLOUD +CLUB +CLUBMED +CM +CN +CO +COACH +CODES +COFFEE +COLLEGE +COLOGNE +COM +COMCAST +COMMBANK +COMMUNITY +COMPANY +COMPARE +COMPUTER +COMSEC +CONDOS +CONSTRUCTION +CONSULTING +CONTACT +CONTRACTORS +COOKING +COOKINGCHANNEL +COOL +COOP +CORSICA +COUNTRY +COUPON +COUPONS +COURSES +CPA +CR +CREDIT +CREDITCARD +CREDITUNION +CRICKET +CROWN +CRS +CRUISE +CRUISES +CU +CUISINELLA +CV +CW +CX +CY +CYMRU +CYOU +CZ +DABUR +DAD +DANCE +DATA +DATE +DATING +DATSUN +DAY +DCLK +DDS +DE +DEAL +DEALER +DEALS +DEGREE +DELIVERY +DELL +DELOITTE +DELTA +DEMOCRAT +DENTAL +DENTIST +DESI +DESIGN +DEV +DHL +DIAMONDS +DIET +DIGITAL +DIRECT +DIRECTORY +DISCOUNT +DISCOVER +DISH +DIY +DJ +DK +DM +DNP +DO +DOCS +DOCTOR +DOG +DOMAINS +DOT +DOWNLOAD +DRIVE +DTV +DUBAI +DUNLOP +DUPONT +DURBAN +DVAG +DVR +DZ +EARTH +EAT +EC +ECO +EDEKA +EDU +EDUCATION +EE +EG +EMAIL +EMERCK +ENERGY +ENGINEER +ENGINEERING +ENTERPRISES +EPSON +EQUIPMENT +ER +ERICSSON +ERNI +ES +ESQ +ESTATE +ET +ETISALAT +EU +EUROVISION +EUS +EVENTS +EXCHANGE +EXPERT +EXPOSED +EXPRESS +EXTRASPACE +FAGE +FAIL +FAIRWINDS +FAITH +FAMILY +FAN +FANS +FARM +FARMERS +FASHION +FAST +FEDEX +FEEDBACK +FERRARI +FERRERO +FI +FIAT +FIDELITY +FIDO +FILM +FINAL +FINANCE +FINANCIAL +FIRE +FIRESTONE +FIRMDALE +FISH +FISHING +FIT +FITNESS +FJ +FK +FLICKR +FLIGHTS +FLIR +FLORIST +FLOWERS +FLY +FM +FO +FOO +FOOD +FOODNETWORK +FOOTBALL +FORD +FOREX +FORSALE +FORUM +FOUNDATION +FOX +FR +FREE +FRESENIUS +FRL +FROGANS +FRONTDOOR +FRONTIER +FTR +FUJITSU +FUN +FUND +FURNITURE +FUTBOL +FYI +GA +GAL +GALLERY +GALLO +GALLUP +GAME +GAMES +GAP +GARDEN +GAY +GB +GBIZ +GD +GDN +GE +GEA +GENT +GENTING +GEORGE +GF +GG +GGEE +GH +GI +GIFT +GIFTS +GIVES +GIVING +GL +GLASS +GLE +GLOBAL +GLOBO +GM +GMAIL +GMBH +GMO +GMX +GN +GODADDY +GOLD +GOLDPOINT +GOLF +GOO +GOODYEAR +GOOG +GOOGLE +GOP +GOT +GOV +GP +GQ +GR +GRAINGER +GRAPHICS +GRATIS +GREEN +GRIPE +GROCERY +GROUP +GS +GT +GU +GUARDIAN +GUCCI +GUGE +GUIDE +GUITARS +GURU +GW +GY +HAIR +HAMBURG +HANGOUT +HAUS +HBO +HDFC +HDFCBANK +HEALTH +HEALTHCARE +HELP +HELSINKI +HERE +HERMES +HGTV +HIPHOP +HISAMITSU +HITACHI +HIV +HK +HKT +HM +HN +HOCKEY +HOLDINGS +HOLIDAY +HOMEDEPOT +HOMEGOODS +HOMES +HOMESENSE +HONDA +HORSE +HOSPITAL +HOST +HOSTING +HOT +HOTELES +HOTELS +HOTMAIL +HOUSE +HOW +HR +HSBC +HT +HU +HUGHES +HYATT +HYUNDAI +IBM +ICBC +ICE +ICU +ID +IE +IEEE +IFM +IKANO +IL +IM +IMAMAT +IMDB +IMMO +IMMOBILIEN +IN +INC +INDUSTRIES +INFINITI +INFO +ING +INK +INSTITUTE +INSURANCE +INSURE +INT +INTERNATIONAL +INTUIT +INVESTMENTS +IO +IPIRANGA +IQ +IR +IRISH +IS +ISMAILI +IST +ISTANBUL +IT +ITAU +ITV +JAGUAR +JAVA +JCB +JE +JEEP +JETZT +JEWELRY +JIO +JLL +JM +JMP +JNJ +JO +JOBS +JOBURG +JOT +JOY +JP +JPMORGAN +JPRS +JUEGOS +JUNIPER +KAUFEN +KDDI +KE +KERRYHOTELS +KERRYLOGISTICS +KERRYPROPERTIES +KFH +KG +KH +KI +KIA +KIDS +KIM +KINDER +KINDLE +KITCHEN +KIWI +KM +KN +KOELN +KOMATSU +KOSHER +KP +KPMG +KPN +KR +KRD +KRED +KUOKGROUP +KW +KY +KYOTO +KZ +LA +LACAIXA +LAMBORGHINI +LAMER +LANCASTER +LANCIA +LAND +LANDROVER +LANXESS +LASALLE +LAT +LATINO +LATROBE +LAW +LAWYER +LB +LC +LDS +LEASE +LECLERC +LEFRAK +LEGAL +LEGO +LEXUS +LGBT +LI +LIDL +LIFE +LIFEINSURANCE +LIFESTYLE +LIGHTING +LIKE +LILLY +LIMITED +LIMO +LINCOLN +LINDE +LINK +LIPSY +LIVE +LIVING +LK +LLC +LLP +LOAN +LOANS +LOCKER +LOCUS +LOFT +LOL +LONDON +LOTTE +LOTTO +LOVE +LPL +LPLFINANCIAL +LR +LS +LT +LTD +LTDA +LU +LUNDBECK +LUXE +LUXURY +LV +LY +MA +MACYS +MADRID +MAIF +MAISON +MAKEUP +MAN +MANAGEMENT +MANGO +MAP +MARKET +MARKETING +MARKETS +MARRIOTT +MARSHALLS +MASERATI +MATTEL +MBA +MC +MCKINSEY +MD +ME +MED +MEDIA +MEET +MELBOURNE +MEME +MEMORIAL +MEN +MENU +MERCKMSD +MG +MH +MIAMI +MICROSOFT +MIL +MINI +MINT +MIT +MITSUBISHI +MK +ML +MLB +MLS +MM +MMA +MN +MO +MOBI +MOBILE +MODA +MOE +MOI +MOM +MONASH +MONEY +MONSTER +MORMON +MORTGAGE +MOSCOW +MOTO +MOTORCYCLES +MOV +MOVIE +MP +MQ +MR +MS +MSD +MT +MTN +MTR +MU +MUSEUM +MUSIC +MUTUAL +MV +MW +MX +MY +MZ +NA +NAB +NAGOYA +NAME +NATURA +NAVY +NBA +NC +NE +NEC +NET +NETBANK +NETFLIX +NETWORK +NEUSTAR +NEW +NEWS +NEXT +NEXTDIRECT +NEXUS +NF +NFL +NG +NGO +NHK +NI +NICO +NIKE +NIKON +NINJA +NISSAN +NISSAY +NL +NO +NOKIA +NORTHWESTERNMUTUAL +NORTON +NOW +NOWRUZ +NOWTV +NP +NR +NRA +NRW +NTT +NU +NYC +NZ +OBI +OBSERVER +OFFICE +OKINAWA +OLAYAN +OLAYANGROUP +OLDNAVY +OLLO +OM +OMEGA +ONE +ONG +ONL +ONLINE +OOO +OPEN +ORACLE +ORANGE +ORG +ORGANIC +ORIGINS +OSAKA +OTSUKA +OTT +OVH +PA +PAGE +PANASONIC +PARIS +PARS +PARTNERS +PARTS +PARTY +PASSAGENS +PAY +PCCW +PE +PET +PF +PFIZER +PG +PH +PHARMACY +PHD +PHILIPS +PHONE +PHOTO +PHOTOGRAPHY +PHOTOS +PHYSIO +PICS +PICTET +PICTURES +PID +PIN +PING +PINK +PIONEER +PIZZA +PK +PL +PLACE +PLAY +PLAYSTATION +PLUMBING +PLUS +PM +PN +PNC +POHL +POKER +POLITIE +PORN +POST +PR +PRAMERICA +PRAXI +PRESS +PRIME +PRO +PROD +PRODUCTIONS +PROF +PROGRESSIVE +PROMO +PROPERTIES +PROPERTY +PROTECTION +PRU +PRUDENTIAL +PS +PT +PUB +PW +PWC +PY +QA +QPON +QUEBEC +QUEST +RACING +RADIO +RE +READ +REALESTATE +REALTOR +REALTY +RECIPES +RED +REDSTONE +REDUMBRELLA +REHAB +REISE +REISEN +REIT +RELIANCE +REN +RENT +RENTALS +REPAIR +REPORT +REPUBLICAN +REST +RESTAURANT +REVIEW +REVIEWS +REXROTH +RICH +RICHARDLI +RICOH +RIL +RIO +RIP +RO +ROCHER +ROCKS +RODEO +ROGERS +ROOM +RS +RSVP +RU +RUGBY +RUHR +RUN +RW +RWE +RYUKYU +SA +SAARLAND +SAFE +SAFETY +SAKURA +SALE +SALON +SAMSCLUB +SAMSUNG +SANDVIK +SANDVIKCOROMANT +SANOFI +SAP +SARL +SAS +SAVE +SAXO +SB +SBI +SBS +SC +SCA +SCB +SCHAEFFLER +SCHMIDT +SCHOLARSHIPS +SCHOOL +SCHULE +SCHWARZ +SCIENCE +SCOT +SD +SE +SEARCH +SEAT +SECURE +SECURITY +SEEK +SELECT +SENER +SERVICES +SES +SEVEN +SEW +SEX +SEXY +SFR +SG +SH +SHANGRILA +SHARP +SHAW +SHELL +SHIA +SHIKSHA +SHOES +SHOP +SHOPPING +SHOUJI +SHOW +SHOWTIME +SI +SILK +SINA +SINGLES +SITE +SJ +SK +SKI +SKIN +SKY +SKYPE +SL +SLING +SM +SMART +SMILE +SN +SNCF +SO +SOCCER +SOCIAL +SOFTBANK +SOFTWARE +SOHU +SOLAR +SOLUTIONS +SONG +SONY +SOY +SPA +SPACE +SPORT +SPOT +SR +SRL +SS +ST +STADA +STAPLES +STAR +STATEBANK +STATEFARM +STC +STCGROUP +STOCKHOLM +STORAGE +STORE +STREAM +STUDIO +STUDY +STYLE +SU +SUCKS +SUPPLIES +SUPPLY +SUPPORT +SURF +SURGERY +SUZUKI +SV +SWATCH +SWISS +SX +SY +SYDNEY +SYSTEMS +SZ +TAB +TAIPEI +TALK +TAOBAO +TARGET +TATAMOTORS +TATAR +TATTOO +TAX +TAXI +TC +TCI +TD +TDK +TEAM +TECH +TECHNOLOGY +TEL +TEMASEK +TENNIS +TEVA +TF +TG +TH +THD +THEATER +THEATRE +TIAA +TICKETS +TIENDA +TIFFANY +TIPS +TIRES +TIROL +TJ +TJMAXX +TJX +TK +TKMAXX +TL +TM +TMALL +TN +TO +TODAY +TOKYO +TOOLS +TOP +TORAY +TOSHIBA +TOTAL +TOURS +TOWN +TOYOTA +TOYS +TR +TRADE +TRADING +TRAINING +TRAVEL +TRAVELCHANNEL +TRAVELERS +TRAVELERSINSURANCE +TRUST +TRV +TT +TUBE +TUI +TUNES +TUSHU +TV +TVS +TW +TZ +UA +UBANK +UBS +UG +UK +UNICOM +UNIVERSITY +UNO +UOL +UPS +US +UY +UZ +VA +VACATIONS +VANA +VANGUARD +VC +VE +VEGAS +VENTURES +VERISIGN +VERSICHERUNG +VET +VG +VI +VIAJES +VIDEO +VIG +VIKING +VILLAS +VIN +VIP +VIRGIN +VISA +VISION +VIVA +VIVO +VLAANDEREN +VN +VODKA +VOLKSWAGEN +VOLVO +VOTE +VOTING +VOTO +VOYAGE +VU +VUELOS +WALES +WALMART +WALTER +WANG +WANGGOU +WATCH +WATCHES +WEATHER +WEATHERCHANNEL +WEBCAM +WEBER +WEBSITE +WED +WEDDING +WEIBO +WEIR +WF +WHOSWHO +WIEN +WIKI +WILLIAMHILL +WIN +WINDOWS +WINE +WINNERS +WME +WOLTERSKLUWER +WOODSIDE +WORK +WORKS +WORLD +WOW +WS +WTC +WTF +XBOX +XEROX +XFINITY +XIHUAN +XIN +XN--11B4C3D +XN--1CK2E1B +XN--1QQW23A +XN--2SCRJ9C +XN--30RR7Y +XN--3BST00M +XN--3DS443G +XN--3E0B707E +XN--3HCRJ9C +XN--3PXU8K +XN--42C2D9A +XN--45BR5CYL +XN--45BRJ9C +XN--45Q11C +XN--4DBRK0CE +XN--4GBRIM +XN--54B7FTA0CC +XN--55QW42G +XN--55QX5D +XN--5SU34J936BGSG +XN--5TZM5G +XN--6FRZ82G +XN--6QQ986B3XL +XN--80ADXHKS +XN--80AO21A +XN--80AQECDR1A +XN--80ASEHDB +XN--80ASWG +XN--8Y0A063A +XN--90A3AC +XN--90AE +XN--90AIS +XN--9DBQ2A +XN--9ET52U +XN--9KRT00A +XN--B4W605FERD +XN--BCK1B9A5DRE4C +XN--C1AVG +XN--C2BR7G +XN--CCK2B3B +XN--CCKWCXETD +XN--CG4BKI +XN--CLCHC0EA0B2G2A9GCD +XN--CZR694B +XN--CZRS0T +XN--CZRU2D +XN--D1ACJ3B +XN--D1ALF +XN--E1A4C +XN--ECKVDTC9D +XN--EFVY88H +XN--FCT429K +XN--FHBEI +XN--FIQ228C5HS +XN--FIQ64B +XN--FIQS8S +XN--FIQZ9S +XN--FJQ720A +XN--FLW351E +XN--FPCRJ9C3D +XN--FZC2C9E2C +XN--FZYS8D69UVGM +XN--G2XX48C +XN--GCKR3F0F +XN--GECRJ9C +XN--GK3AT1E +XN--H2BREG3EVE +XN--H2BRJ9C +XN--H2BRJ9C8C +XN--HXT814E +XN--I1B6B1A6A2E +XN--IMR513N +XN--IO0A7I +XN--J1AEF +XN--J1AMH +XN--J6W193G +XN--JLQ480N2RG +XN--JLQ61U9W7B +XN--JVR189M +XN--KCRX77D1X4A +XN--KPRW13D +XN--KPRY57D +XN--KPUT3I +XN--L1ACC +XN--LGBBAT1AD8J +XN--MGB9AWBF +XN--MGBA3A3EJT +XN--MGBA3A4F16A +XN--MGBA7C0BBN0A +XN--MGBAAKC7DVF +XN--MGBAAM7A8H +XN--MGBAB2BD +XN--MGBAH1A3HJKRD +XN--MGBAI9AZGQP6J +XN--MGBAYH7GPA +XN--MGBBH1A +XN--MGBBH1A71E +XN--MGBC0A9AZCG +XN--MGBCA7DZDO +XN--MGBCPQ6GPA1A +XN--MGBERP4A5D4AR +XN--MGBGU82A +XN--MGBI4ECEXP +XN--MGBPL2FH +XN--MGBT3DHD +XN--MGBTX2B +XN--MGBX4CD0AB +XN--MIX891F +XN--MK1BU44C +XN--MXTQ1M +XN--NGBC5AZD +XN--NGBE9E0A +XN--NGBRX +XN--NODE +XN--NQV7F +XN--NQV7FS00EMA +XN--NYQY26A +XN--O3CW4H +XN--OGBPF8FL +XN--OTU796D +XN--P1ACF +XN--P1AI +XN--PGBS0DH +XN--PSSY2U +XN--Q7CE6A +XN--Q9JYB4C +XN--QCKA1PMC +XN--QXA6A +XN--QXAM +XN--RHQV96G +XN--ROVU88B +XN--RVC1E0AM3E +XN--S9BRJ9C +XN--SES554G +XN--T60B56A +XN--TCKWE +XN--TIQ49XQYJ +XN--UNUP4Y +XN--VERMGENSBERATER-CTB +XN--VERMGENSBERATUNG-PWB +XN--VHQUV +XN--VUQ861B +XN--W4R85EL8FHU5DNRA +XN--W4RS40L +XN--WGBH1C +XN--WGBL6A +XN--XHQ521B +XN--XKC2AL3HYE2A +XN--XKC2DL3A5EE0H +XN--Y9A3AQ +XN--YFRO4I67O +XN--YGBI2AMMX +XN--ZFR164B +XXX +XYZ +YACHTS +YAHOO +YAMAXUN +YANDEX +YE +YODOBASHI +YOGA +YOKOHAMA +YOU +YOUTUBE +YT +YUN +ZA +ZAPPOS +ZARA +ZERO +ZIP +ZM +ZONE +ZUERICH +ZW +` + +var tlds = strings.Split(strings.TrimSpace(tldsByAlpha), "\n") diff --git a/update_tld.sh b/update_tld.sh new file mode 100755 index 0000000..779320b --- /dev/null +++ b/update_tld.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +set -eu + +TLD_URL=https://data.iana.org/TLD/tlds-alpha-by-domain.txt +TLD="$(curl -fsSL https://data.iana.org/TLD/tlds-alpha-by-domain.txt | grep -v '^#')" + +cat > tld.go << EOF +// Copyright 2020 Walter Scheper +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +package rapid + +import "strings" + +// sourced from https://data.iana.org/TLD/tlds-alpha-by-domain.txt +// Version $(date +%Y%m%d00), Last Updated $(date -u) +const tldsByAlpha = \` +${TLD} +\` + +var tlds = strings.Split(strings.TrimSpace(tldsByAlpha), "\n") +EOF diff --git a/url.go b/url.go new file mode 100644 index 0000000..4be8307 --- /dev/null +++ b/url.go @@ -0,0 +1,127 @@ +// Copyright 2020 Walter Scheper +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +package rapid + +import ( + "fmt" + "net/url" + "reflect" + "strings" + "unicode" +) + +const ( + domainMaxLength = 255 + domainMaxElementLength = 63 +) + +var ( + domainType = reflect.TypeOf("") + urlType = reflect.TypeOf(url.URL{}) +) + +type domainNameGen struct{} + +func (*domainNameGen) String() string { + return "Domain()" +} + +var tldGenerator = SampledFrom(tlds) + +func (g *domainNameGen) value(t *T) string { + domain := tldGenerator. + Filter(func(s string) bool { return len(s)+2 <= domainMaxLength }). + Draw(t, "domain") + + expr := fmt.Sprintf(`[a-zA-Z]([a-zA-Z0-9\-]{0,%d}[a-zA-Z0-9])?`, domainMaxElementLength-2) + elements := newRepeat(1, 126, 1, g.String()) + for elements.more(t.s) { + subDomain := StringMatching(expr).Draw(t, "subdomain") + if len(domain)+len(subDomain) >= domainMaxLength { + break + } + domain = subDomain + "." + domain + } + + return domain +} + +// Domain generates an RFC 1035 compliant domain name. +func Domain() *Generator[string] { + return newGenerator[string](&domainNameGen{}) +} + +type urlGenerator struct { + schemes []string +} + +func (g *urlGenerator) String() string { + return "URL()" +} + +var printableGen = StringOf(RuneFrom(nil, unicode.PrintRanges...)) + +func (g *urlGenerator) value(t *T) url.URL { + scheme := SampledFrom(g.schemes).Draw(t, "scheme") + var domain string + switch SampledFrom([]int{0, 1, 2}).Draw(t, "g") { + case 2: + domain = Domain().Draw(t, "domain") + case 1: + domain = IPv6().Draw(t, "domain").String() + domain = "[" + domain + "]" + case 0: + domain = IPv4().Draw(t, "domain").String() + } + + port := Transform(IntRange(0, 2^16-1), func(i int) string { + if i == 0 { + return "" + } + + return fmt.Sprintf(":%d", i) + }).Draw(t, "port") + + path_ := Transform(SliceOf(printableGen), func(paths []string) string { + // URL escape path + for i := range paths { + paths[i] = url.PathEscape(paths[i]) + } + + return strings.Join(paths, "/") + }).Draw(t, "path") + + query := Transform(SliceOf(printableGen), func(queries []string) string { + // url escape query strings + for i := range queries { + queries[i] = url.QueryEscape(queries[i]) + } + + return strings.Join(queries, "&") + }).Draw(t, "query") + + fragment := printableGen.Draw(t, "fragment") + + return url.URL{ + Host: domain + port, + Path: path_, + Scheme: scheme, + RawQuery: query, + Fragment: fragment, + } +} + +// URL generates RFC 3986 compliant http/https URLs. +func URL() *Generator[url.URL] { + return urlOf([]string{"http", "https"}) +} + +func urlOf(schemes []string) *Generator[url.URL] { + return newGenerator[url.URL](&urlGenerator{ + schemes: schemes, + }) +} diff --git a/url_example_test.go b/url_example_test.go new file mode 100644 index 0000000..a6a125a --- /dev/null +++ b/url_example_test.go @@ -0,0 +1,44 @@ +// Copyright 2020 Walter Scheper +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +package rapid_test + +import ( + "fmt" + + "pgregory.net/rapid" +) + +func ExampleDomain() { + gen := rapid.Domain() + + for i := 0; i < 5; i++ { + fmt.Println(gen.Example(i)) + } + + // Output: + // l.UOL + // S.CYMRU + // e.ABBVIE + // x.ACCOUNTANTS + // R.AAA +} + +func ExampleURL() { + gen := rapid.URL() + + for i := 0; i < 5; i++ { + e := gen.Example(i) + fmt.Println(e.String()) + } + + // Output: + // https://[e506:816b:407:316:fb4c:ffa0:e208:dc0e]/%25F0%2597%25B0%25A0%25F0%2592%2591%259CX/1=%2522?%C4%90%F0%90%A9%87%26#%F0%96%AC%B21%CC%88%CC%81D + // http://Z.BLOOMBERG:2/%25E2%259C%25A1/1%25F0%2591%2588%25BD/%25F0%259F%25AF%258A%2522%25D6%2593%25E0%25A9%25AD%25E1%25B3%25930%25D0%258A/%25C2%25BC%25E0%25B4%25BC3%25F0%259D%259F%25B9%25F0%2591%2591%2582%25C2%25B2%25E0%25B3%25A9%25CC%2580D/%257C+%25F0%259F%2582%2592+%255D%25CC%2581%25CB%2585/%25CC%2580/%25E1%25B0%25BF/%25CD%2582K%25E0%25A5%25A9%25CC%2581#%CC%82 + // https://1.47.4.5:11/+%253E%25E2%259F%25BCK//A%25DB%2597%25F0%2591%2599%2583$%25E0%25A0%25BD%25E2%2582%25A5%25F0%259D%25A9%25A9%25E0%25BC%2595%25E0%25B5%25A8%253C%25E0%25BE%25AE%25F0%2597%258A%25B1%25E2%259E%258E%25E0%25B9%2591$v%25CC%2580/%25CC%2594Z%25E4%2587%2594?%F0%96%A9%AEC%C2%B9%E2%8A%A5%F0%92%91%B41%E0%A0%BE%CB%BE%C3%9D%E1%B3%A4%E0%AB%A6%CC%81%CC%86&%E2%A4%88%F0%91%BF%BF%24B%F0%96%BA%90%CC%9A&&%CC%80%C2%A7%E8%93%8B&#%E0%AB%AE%F0%92%91%91 + // http://J.HOMESENSE/%25F0%259B%2589%259D%25C2%25B86%25CC%2580%25F0%259E%25A5%259F/:%2521J%25E2%259D%2587#L%CC%82%E9%98%8C%22 + // http://1.1.4.6:2/%25F0%25A7%25A8%25A4%25F0%25A1%25AD%258D%25E2%2592%258B0/%25DC%25B4B?%E2%80%A60%CC%80%C3%B7&%CC%81%CC%A2%21%E0%AF%AB%CC%81%C3%A4&%F0%9F%AF%8A%EA%99%AF%CC%80%E0%A5%AD&%E5%8B%B71&%E1%B7%8F%CC%8B%E2%87%94%E2%90%8E%EA%A3%A0%E0%B5%9A%3D%E5%8E%8A%D9%AAB%F0%A8%83%A2%EF%B8%B4%E0%A0%BD%F0%9D%84%86%C6%81%211A3&%E1%81%8F%23#%CC%80%E0%BF%8B+$ +} diff --git a/url_external_test.go b/url_external_test.go new file mode 100644 index 0000000..3adecbe --- /dev/null +++ b/url_external_test.go @@ -0,0 +1,48 @@ +// Copyright 2020 Walter Scheper +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. + +package rapid_test + +import ( + "net/url" + "strings" + "testing" + + . "pgregory.net/rapid" +) + +func TestURL(t *testing.T) { + t.Parallel() + + Check(t, func(t *T) { + u := URL().Draw(t, "url") + + // should be parsable + if _, err := url.Parse(u.String()); err != nil { + t.Fatalf("URL returned unparsable url %s: %v", u.String(), err) + } + }) +} + +func TestDomain(t *testing.T) { + t.Parallel() + + Check(t, func(t *T) { + d := Domain().Draw(t, "d") + if got, want := len(d), 255; got > want { + t.Errorf("got domain of length %d with maxLength of %d", got, want) + } + + elements := strings.Split(d, ".") + + // ignore the tld + for i, elem := range elements[:len(elements)-1] { + if got, want := len(elem), 63; got > want { + t.Errorf("got domain element %d of length %d with maxElementLength %d", i, got, want) + } + } + }) +}