text:
Rodents /
Mice and Rats as Pets /
Bacterial Infections: Viral Infections: Parasitic Infections: Fungal Infections:
Neoplasia
Miscellaneous and Iatrogenic Disorders
Dental Overgrowth: Age-related Disorders: Skin Disease in Mice: Chromodacryorrhea in Rats:
Zoonotic Risk
Overview of Rodents
Mice and Rats as Pets
Mice and Rats as Laboratory Animals
Thomas M. Donnelly
, BVSc, DVP, DACLAM, DABVP(ECM), The Kenneth S Warren Institute
Last full review/revision Sep 2015 | Content last modified Oct 2015
Sialodacryoadenitis, rat
Destruction of ductal epithelial cells, parotid salivary gland, rat
Eggs of Aspicularis tetraptera (pinworms)
Egg of Syphacia muris
Myobia musculi lesions, mouse
Ringtail, rat
Chromodacryorrhea ("red tears"), rat
Mice and rats are not as common as pets as other rodents. They are used extensively in research and, consequently, a separate section on mice and rats as laboratory animals follows below (see Mice and Rats as Laboratory Animals). Although a great deal of information has been accumulated on wild and laboratory rodents, very little of this information pertains to pet rodents.
The prevalence and type of mouse and rat diseases seen in clinical practice are quite different from those seen in a research setting. The diagnosis and treatment of pet mice and rats involves evaluation and care of an individual animal from a household, not the health management of rodents from a research colony. Most problems in mice and rats are dermatopathies, respiratory infections, and neoplasia.
Male rats are sexually mature by 6–10 wk; female rats are sexually mature by 8–12 wk. The breeding life of both male and female rats is 9–12 mo. Estrous cycle length in female rats is 4–5 days, and estrus lasts 10–20 hr. Female rats ovulate ~10–20 eggs. Gestation lasts 21–23 days; pseudopregnancy from sterile matings lasts 12 days. Rats have an average litter size of 8–18 pups. Weaning takes place at ~21 days.
Both male and female mice are sexually mature by 6–8 wk and have a breeding life of 9 mo. Estrous cycle length in female mice is 4–5 days, and estrus lasts 10–20 hr. Female mice ovulate ~6–10 eggs. Gestation lasts 19–21 days; pseudopregnancy from sterile matings lasts 12 days. Mice have an average litter size of 5–12 pups. Weaning takes place at ~21 days.
Male mice and rats produce a small amount of sperm daily at puberty (eg, 40–50 days in a rat). It is not until 75–100 days (10–14 wk) in rats that optimal sperm production and reserve occur. Male rodents show a constant libido after sexual maturity; in contrast, females are receptive to copulation only during estrus. Males cannot fertilize females until 6–8 wk after reaching puberty.
The average life span of mice is 18–24 mo and of rats 18–36 mo. Restricting dietary calories without compromising overall nutrition results in increased life span. Obesity in pet rats and mice is common, and calorie-restricted pets live significantly longer lives.
The best cages are made of a material that is easy to clean and deodorize and is indestructible to rodent chewing or digging in the corners. The cage floor can be solid but should be waterproof and easy to clean. Wire mesh floors should be avoided, because rats and mice can trap their feet and especially hindlimbs in the openings, resulting in fractures and injuries.
Animal cage bedding is described based on its use (eg, contact, noncontact, and enrichment bedding) or the material from which it is made (eg, wood-based [chips, shavings, peelings, wood-wool and sawdust], paper-based [cotton and pulp fiber, recycled paper], corn [husks and cobs], cellulose, and vermiculite). The purpose of bedding is to keep animals dry and clean. Pet owners generally choose bedding based on cost and availability, whereas laboratory veterinarians choose bedding based on cost and water-holding capacity. Some pet bedding contains lemon and chlorophyll to give it a pleasant scent. This type of bedding irritates pet rodents, and the coloring agents can stain the coat of white rats or mice. Traditionally, owners prefer paper and softwood chips, such as pine or aspen, to straw because it requires fewer bedding changes. Cedar and other wood chip shavings reduce ectoparasite problems and have a pleasant scent. However, such bedding is not recommended, because it emits toxic aromatic hydrocarbons that increase the incidence of cancer in animals and cause mouse and rat pup mortality.
Owners must combine frequent bedding changes with good husbandry such as regular cage cleaning, low animal density, and low environmental temperature and humidity. This will reduce toxic or odor-causing gases such as ammonia from building up, because urease-positive bacteria in the feces act to break down urea in the urine. Aquariums are not suitable cages for rats and mice because of inadequate air circulation and subsequent buildup of ammonia. Environmental temperature and relative humidity can depend on husbandry and housing design and can differ considerably between the cage and room. Factors that contribute to variation in temperature and humidity include cage material and construction, number of animals per cage, frequency of bedding changes, and bedding type.
Size and manipulability of bedding material are the main determinants of mice and rats' choices. Mice and rats avoid bedding consisting of small particles, whereas they prefer bedding consisting of large, fibrous particles. When exposed to different types of nesting materials such as paper strips, cornhusks, sawdust, and wood materials (shavings, peelings, and chips), rats choose long strips of soft paper. Rats also select opaque or semiopaque nest boxes to transparent nest boxes. Mice show no preference between paper and wood-derived materials but show a clear preference for materials that they can manipulate such as paper tissues, string, and wood materials (shavings, peelings, and chips). Many mice will combine two preferred nesting materials to make complex nests. Mice typically dislike wire-bottomed cages; however, both male and female mice will spend more time in a wire-bottomed cage with nesting material, despite the grid floor that they usually avoid.
In environmentally enriched cages with hollow tubes, mice have no overwhelming group preference for shape, opacity, or openness of tubes and prefer to sleep in sawdust when it is available. Mice will sleep in hollow tubes only after the sawdust is removed; they use short, wide tubes more frequently than long or short narrow tubes.
Mice and rats are optimally maintained at temperatures of 64°–79°F (18°–26°C). Relative humidity should also be controlled but not nearly as narrowly as temperature. An acceptable range of relative humidity is 30%–70%. Both temperature and humidity regulation are important to prevent ringtail and exacerbation of respiratory disease. Avascular necrosis of the tail, or ringtail, occurs primarily in young rats in low-humidity environments. Excess heat and humidity cause heat stroke and indirectly cause decompensation of chronic respiratory disease, resulting in death.
Mouse and rat owners should check water bottles daily. If mice are deprived of water for only a short time and experience dramatic fluctuations in the surrounding temperature, especially >99°F (37°C), they die. In contrast, healthy rats tolerate water deprivation and temperature fluctuations better. They can live for 7 days without water, in temperatures between 64°–79°F (18°–26°C), although they may lose up to 65% of their body weight.
Minimal space allocations of 23 sq in. (58 sq cm) are recommended for individual rats weighing ≤200 g, and 60 sq in. (152 sq cm) for rats weighing ≥ 500 g. For mice, minimal space allocations of 15 sq in (38 sq cm) for individual mice weighing >25 g are recommended. These are small surface areas, and veterinarians should advocate that owners provide larger space for their pets.
Most rodent enrichment studies focus on modifying the area inside the enclosure rather than the size of an enclosure. However, rats prefer larger cages, and experimental studies suggest rats should have a larger space that allows sharing of the environment with up to four other rats.
The minimum recommended height of cages should take into account typical postures of rats and mice. This includes the animal standing fully erect on its hindlegs, and vertical movements such as stretching upward and possibly climbing. Consequently, minimal cage heights of 12–15 in. (30–38 cm) for rats and 7–8 in. (18–20 cm) for mice are recommended.
Environmental enrichment is important for both mice and rats. For example, suspended cloth hammocks are popular with rats, and suspended (plastic or stainless steel) shower hooks fitted into one another can make a swinging chain. Rats will use more enrichment devices than mice, but they usually stop using the devices after 3–4 days. Rotation of enrichment toys and introduction of novel devices excite their curiosity. Food treats are also valuable enrichment items. These can range from simple, inexpensive treats such as a daily piece of a breakfast cereal to formulated nutritious or calorie-free treats. Rats also love chocolate, and it is not toxic when fed in small amounts. Pet rodents accustomed to handling will eat food treats out of the owner's hand. This daily routine can allow owners to detect subtle changes in the pet's behavior. Sick rodents effectively hide signs of disease. Sick rats do not show the same interest in their daily treat, and this can alert the owner early to disease when it is still treatable and/or reversible.
Housing male and female rodents together will result in mating and subsequent litters. Mice and rats experience postparturient estrus, and fertilization can occur. However, implantation of the resulting blastocysts is delayed during lactation and occurs at weaning, ensuring that the next litter is not born until the earlier one has been weaned. Female mice become sexually mature at 6–8 wk of age, and female rats are sexually mature by 10 wk of age. Unless opposite-sex rodents housed together are separated or neutered, having a new litter every 3–5 wk is possible.
Rats and mice are omnivores and will eat food of both plant and animal origin. In the wild, rats and mice will eat a wide variety of seeds, grains, and other plant material as well as invertebrates, small vertebrates, and carrion. Their ability to scavenge partly accounts for their successful colonization of diverse geographic regions.
Formulated pelleted diets for laboratory rodents are convenient and nutritionally balanced diets for early life and reproduction. However, laboratory rodent diets are relatively high in fat and low in fiber, and when provided ad libitum, they cause obesity. Consequently, the amount of pelleted diet owners provide daily should be limited. Diets formulated specifically for pet rodents are now commercially available. Owners should supplement their pet's diet with feeds high in fiber such as vegetables, limited amounts of fruit, and occasional treats.
Coprophagy is a normal behavior in rats and mice. It is an inherent behavior, because it is seen in germ-free rodents purposely bred for research. Unlike rabbits, which eat cecal feces from their anus, mice and rats eat fecal pellets on the floor of their caging. The amount of feces eaten varies between rodents, their age and physiologic status (eg, coprophagy increases in pregnancy), and the diet fed. On a nutritionally complete diet, rats will eat ~10% of their feces. When rats are housed together, they ingest each other's feces. The unique odor of a colony is due in part to ingestion of feces, and the group scent enables distinction between members and nonmembers. Mice engage in coprophagy ~6 times/day. Growing mice show vigorous coprophagous activity, eating 13 pellets/day. However, it gradually decreases to 1½ pellets at 2 yr of age.
Owners should house different species of rodents separately to prevent interspecies disease transmission. For example, rats carry Streptobacillus moniliformis (see Global Zoonoses a), a cause of fatal septicemia in mice, as part of the normal nasopharyngeal bacterial flora. Rodents of the same species should be housed in such a way to protect vulnerable animals from more aggressive members of their group. This includes separating young animals from older ones. Female rodents are generally compatible when housed in the same cage, unless one female has lived much of its life alone. Male rats are generally compatible, especially if raised together. However, owners should never house strange male rats in the same cage together because they will fight. Male mice generally fight if housed together, unless they are littermates raised together without females present. Male mice are best housed singly or with female mice.
Rats are social animals, and grooming is a socially affiliative behavior. Singly housed rats may develop isolated-rat stress syndrome if left alone without human contact and environmental enrichment. Isolation-reared rats will experience fighting, physical injuries, and weight loss when placed into a colony of socially experienced rats. Young rats should be housed together to develop social affiliation. Singly housed rats should not be put together. Owners should be advised to encourage enrichment and human contact with pet rats.
Observing the condition of the rodent's living quarters provides useful information. Information obtained from a physical examination is often limited because of the mouse or rat's size. Activity of the rat, condition of grooming, and the presence of a head tilt or discharges in the cage should be noted. If dyspnea or depression is seen, extreme care should be used when handling the animal, because it is probably very sick and could die from the stress of a physical examination.
Pet rodents that have been frequently and gently handled usually require only minimal restraint. Less cooperative animals need to be more firmly restrained, and use of a towel or even heavy gloves may be required. Weight measurement is essential to calculate appropriate dosages of medications and provides an opportunity to gauge the rodent's temperament before beginning the actual physical examination.
The head, ears, eyes, and nose should be examined for discharges, and the oral cavity for dentition. Lymph nodes and glands of the head can be observed for size and palpated for consistency. Assessment of the head is probably the most time-consuming part of the examination. The abdomen can be palpated for consistency and the presence of unusual masses. Animals should not be squeezed too vigorously, because overzealous palpation can result in visceral rupture. The anogenital region should be examined for discharges and staining of the fur or skin. When a rodent is picked up, it generally urinates and defecates. A dipstick should be ready to perform an immediate urinalysis; feces can be caught in a small tube and examined later. The limbs should be palpated for tenderness or fractures, with special attention given to the paws, noting the length of the nails and condition of the footpads.
Respirations and heart rate in mice and rats are rapid and, therefore, difficult to measure. Instead, signs of dyspnea should be noted. Some respiratory infections, such as mycoplasmosis, are clinically silent. These diseases can be better heard than seen; abnormal sounds called "snuffling" in rats and "chattering" in mice are noticeable without a stethoscope.
Bacterial Infections:
Rats are the natural host of the bacterium Streptobacillus moniliformis. It is a commensal organism of the nasopharyngeal flora and does not cause disease in rats. However, individuals bitten by rats may become infected with S moniliformis and develop rat bite fever, a potentially fatal disease (see Global Zoonoses a). Mice housed with rats will become infected with S moniliformis and develop fatal septicemia characterized by polyarthritis, cervical lymphadenitis, pneumonia, and splenomegaly.
Respiratory disease caused by infectious agents is the most common health problem in rats. Three major respiratory pathogens cause overt clinical disease: Mycoplasma pulmonis, Streptococcus pneumoniae, and Corynebacterium kutscheri. Other organisms such as Sendai virus (a paramyxovirus), pneumonia virus of mice (a paramyxovirus), rat respiratory virus (a hantavirus), cilia-associated respiratory (CAR) bacillus, and Haemophilus species are minor respiratory pathogens that rarely cause overt clinical disease by themselves. However, the minor respiratory pathogens interact synergistically as copathogens with the major respiratory pathogens to produce two major clinical syndromes: chronic respiratory disease (CRD) and bacterial pneumonia.
CRD is the best-understood multifactorial respiratory infection in rats. M pulmonis is the major component of CRD, and the disease is also known as murine respiratory mycoplasmosis. Rats with CRD rarely live >2 yr. Clinical signs are highly variable. Initial infection commonly occurs without any clinical signs; early signs involve both the upper and lower respiratory tracts and may include snuffling, nasal discharge, polypnea, weight loss, hunched posture, ruffled coat, head tilt, and red tears. Dyspnea, the primary presenting complaint, is caused by ciliostasis, subsequent buildup of lysozyme-rich inflammatory exudate in airways, bronchiectasis, and bronchiolectasis from inflammatory damage to bronchiolar membranes. Chronic disease often includes middle ear infection (via the eustachian tube). Antibiotic therapy may alleviate clinical signs but does not eliminate the infection. Enrofloxacin (10 mg/kg) and doxycycline (5–10 mg/kg) given orally bid for 14 days often alleviates severe clinical signs. Additional treatments such as daily nebulization therapy with 7% hypertonic saline to break down the mucus biofilm in respiratory passages, bronchodilators (theophylline 10 mg/kg, bid) to improve airway patency, and reducing ammonia levels in cages by daily removal of bedding and use of clean paper will ameliorate the disease. Chronic low dose doxycycline (5–10 mg/kg/day, PO) helps to prevent acute relapses. The doxycycline is both bactericidal for mycoplasma organisms and has a marked immunomodulatory effect on the chronic airway inflammation.
The most important aspect of CRD for clinicians is that respiratory mycoplasmosis varies greatly in disease expression because of environmental, host, and organism factors that influence the host-pathogen relationship. Examples of such factors include intracage ammonia levels; concurrent Sendai virus, coronavirus (sialodacryoadenitis virus), pneumonia virus of mice, rat respiratory virus, and/or CAR bacillus infection; the genetic susceptibility of the host; the virulence of the Mycoplasma strain; and vitamin A or E deficiency. Although CRD is rarely seen in laboratory rats, most pet rats have CRD to some degree. One survey of pet ratteries in the northwest USA showed virtually all (95%) were positive for CAR-bacillus and M pulmonis, and approximately half were positive for other viral respiratory agents.
Bacterial pneumonia is nearly always caused by S pneumoniae, but seldom in the absence of some combination involving M pulmonis, Sendai virus, or CAR bacillus. Infection with C kutscheri also results in pneumonia but only in conjunction with debilitation or immunosuppression. In pet rats, immunosuppression can result from diabetes, neoplasia, or dietary deficiencies. C kutscheri pneumonia is rare in pet rats. Pneumonia caused by S pneumoniae can be of sudden onset. Young rats are more severely affected than older ones, and often the only sign they exhibit is sudden death. Mature rats may demonstrate dyspnea, snuffling, and abdominal breathing. A purulent exudate may be seen around the nares and on the front paws from wiping of the nostrils. A tentative diagnosis is based on identification of numerous gram-positive diplococci on a Gram stain of the exudate or in a sample submitted for cytologic examination. Severe bacteremia is an important consequence of advanced disease and results in multiorgan abscesses and infarction. Treatment is amoxicillin/clavulanic acid (13.75 mg/kg, PO, bid) or β-lactamase–resistant penicillins such as cloxacillin, oxacillin, and dicloxacillin, which can all be administered orally or parenterally.
Ulcerative dermatitis caused by Staphylococcus aureus infection results from self-trauma associated with fur mite infestation or, more commonly, from scratching of the skin over an inflamed salivary gland. Rats have a remarkable ability to resist infection with S aureus. Treatment consists of clipping the toenails of the hindpaws, cleaning the ulcerated skin, and applying a topical antibiotic. Systemic treatment is rarely necessary.
The two most common causes of clinical respiratory disease in mice are Sendai virus and M pulmonis infection. Sendai virus is associated with an acute respiratory infection in which mice display chattering and mild respiratory distress. Neonates and weanlings may die. Adults generally recover within 2 mo. When the disease expression exceeds this pattern, the cause is most likely concurrent mycoplasmal infection. M pulmonis is the cause of chronic pneumonia, suppurative rhinitis, and occasionally otitis media. Chattering and dyspnea are caused by accumulations of purulent exudate in inflamed and thickened nasal passages. Survivors often develop chronic bronchopneumonia, bronchiectasis, and pulmonary abscesses. Antibiotic therapy may alleviate clinical signs but does not eliminate the infection.
Viral Infections:
Viral diseases of mice and rats are common. However, most diseases are subclinical and important only in laboratory animals in which they have the potential to have a significant effect on research.
Sialodacryoadenitis virus, a coronavirus, causes inflammation and edema of the cervical salivary glands in rats. Owners of infected rats often describe their pets as having mumps. Sialodacryoadenitis virus infection is highly contagious. It initially causes rhinitis followed by epithelial necrosis and inflammatory swelling of the salivary and lacrimal glands. Cervical lymph nodes also become enlarged. There is no treatment for this disease. Glandular healing follows within 7–10 days, and clinical signs subside within 30 days, with minimal residual lesions remaining. During acute inflammation, affected rats are at high risk of anesthesia-related mortality because of the decreased diameter of the upper respiratory tract lumen. Ocular lesions such as conjunctivitis, keratitis, corneal ulcers, synechia, and hyphema can develop secondary to lacrimal dysfunction. The eye lesions usually resolve but occasionally progress to chronic keratitis and megaglobus.
Parasitic Infections:
Protozoa:
Endoparasites are relatively common in mice. However, only two parasites regularly encountered in the digestive tract, the protozoan parasites Spironucleus muris and Giardia muris, are considered pathogenic, even though they are not associated with clinical signs in immunocompetent hosts. Diagnosis is based on demonstration of characteristic trophozoites in wet mounts of fresh intestinal contents or feces. Treatment is metronidazole (10–40 mg/kg/day, PO, or 0.04%–0.1% drinking water solution for 14 days), but it does not completely eliminate the infection.
Nematodes:
Pinworms are ubiquitous and considered nonpathogenic in mice. Two are commonly encountered: Syphacia obvelata and Aspicularis tetraptera. Often, the only indication of pinworm infestation is rectal prolapse due to straining. To establish a diagnosis of S obvelata infestation, a clear cellophane tape impression of the perianal skin can be made. Adult S obvelata females deposit ova around the anus. A tetraptera does not deposit its ova in this area, and fecal smear or flotation is required to confirm a diagnosis. Ivermectin (2 mg/kg, PO, given twice at a 10-day interval) eliminates pinworms from mice. The recommended label dosage for mice with ectoparasites (0.2 mg/kg, given twice at a 10-day interval) does not eliminate pinworms.
Mites:
Most infectious causes of alopecia and dermatitis in mice are associated with fur mites. Generalized thinning of the hair, especially on difficult-to-groom areas such as the head and trunk, is seen. The coat often has a greasy appearance and, in cases of heavy infestation, noticeable pruritus and self-inflicted dermal ulceration may occur. Three mites are commonly seen: Myobia musculi, Myocoptes musculinus, and Radfordia affinis. M musculi is the most clinically significant mouse mite. Infestations are usually caused by more than one species. Mites are spread by direct contact with infected mice or infested bedding. Diagnosis is based on identification of adult mites, nymphs, or eggs on hair shafts with the use of a hand lens or stereoscopic microscope. Adults and nymphs appear pearly white and elongate; eggs are oval and can be seen attached to the base of hairs or inside mature females. Mite infestations are treated with ivermectin (0.2 mg/kg, SC or PO, twice at 10-day intervals). Alternatively, a few drops of ivermectin solution (diluted to 1:100 in equal parts of water and propylene glycol for three treatments) can be placed on the mouse's head to allow spread by grooming and ingestion.
Ectoparasitic infestation is less common in rats than in mice. Occasionally, the fur mite Radfordia ensifera is seen. Although R ensifera infestation produces few ill effects, heavy infestation may lead to self-trauma and ulcerative dermatitis.
Ornithonyssus bacoti, the tropical rat mite or red mite, is a bloodsucking parasitic mite primarily found in wild rats such as the brown rat (Rattus norvegicus) or the black roof rat (Rattus rattus). It has a wide host range and occasionally infects pet hamsters, gerbils, rats, and mice living in very old buildings or when building construction or renovations disturb colonies of wild rodents that had been on the premises and acting as hosts. O bacoti can survive for long periods in the environment and travel considerable distances in search of new hosts. If it does not find a suitable rodent host, it will feed on people. Its common name is a misnomer, because it is found worldwide in tropical and temperate climates. Mites appear white before feeding and become red-brown after engorgement. Heavy infestations on pet rodents resemble fine sawdust within the fur. O bacoti typically does not cause clinical signs in pet rodents, but heavy infestations cause anemia, debility, weakness, pruritus, and death in small rodents. As well as causing discomfort, the mite is a vector for the rodent filarial nematode Litomosoides carinii and a potential vector of several human pathogens. Most infestations occur in late spring or early summer when fledglings are leaving the nest and the mites are searching for another food source. Infestation of O bacoti is eliminated by a combination of bathing and treating the host animal with selamectin (15 mg/kg, one topical treatment), elimination of commensal rodent reservoirs, and insecticide treatment of the pet's cage (permethrin-impregnated cotton balls 7.4% placed inside the cage weekly for 6 wk) and environment (fipronil spray or synthetic pyrethroids).
Fungal Infections:
Dermatophytosis is uncommon in pet mice and rats. It is caused by Trichophyton mentagrophytes. Lesions, when present, are most common on the face, head, neck, and tail. The lesions have a scurfy appearance, with patchy areas of alopecia and variable degrees of erythema and crusting. Pruritus is usually minimal to absent, and the lesions do not fluoresce under a Wood's lamp. T mentagrophytes can be isolated from the fur of clinically normal mice but is rare in rats.
The most common subcutaneous tumor in rats is fibroadenoma of the mammary glands. The distribution of the mammary tissue is extensive, and the tumors can develop anywhere from the neck to inguinal region. Tumors can reach 8–10 cm in diameter and are seen in both males and females. The surgical technique for tumor removal is straightforward, and survival after mastectomy has been reported to be good if the tumor is benign. The prevalence of mammary tumors, as well as that of pituitary tumors, is significantly lower in ovariectomized rats than in sexually intact rats. However, the recurrence of fibroadenomas is common in uninvolved mammary tissue, and often several surgeries are needed.
In contrast, mammary tumors in mice are nearly always malignant and often are not amenable to surgical removal. The most common spontaneous tumors associated with the skin are mammary adenocarcinomas, followed by fibrosarcomas. The incidence of mammary tumors varies according to the mouse strain and the presence or absence of mouse mammary tumor viruses; the incidence is as high as 70% in some strains. In wild and outbred mice, the incidence of fibrosarcomas is 1%–6%.
Subcutaneous tumors are nearly always malignant and often have ulcerated by the time a diagnosis is made. Tumors can be treated by surgical excision, but the chance of recurrence is high and the prognosis is poor.
Dental Overgrowth:
Dental problems are commonly seen in pet mice and rats because of their continually erupting teeth. Overgrown incisors are seen most frequently in rats and mice, in contrast with molar occlusion seen in guinea pigs and chinchillas. Overgrowth is easily treated with a high-speed drill that cuts through the overgrown incisors without splitting or splintering them, leaving a clean, smooth surface. Cutting the teeth with rongeurs does not produce good longterm results, and problems may arise. The incisor may fracture longitudinally; the fracture may reach the apex and cause the animal discomfort. Bacteria can enter the fractured tooth, track down to the apex, and cause an apical abscess. Extraction of the incisors is an alternative to trimming; however, this procedure is difficult because of the incisors' long roots.
Age-related Disorders:
Chronic progressive nephrosis is a common age-related disease in rats. The kidneys are enlarged, pale, and have a pitted, mottled surface that often contains pinpoint cysts. Lesions consist of a progressive glomerulosclerosis and widespread tubulointerstitial disease, primarily involving the proximal convoluted tubule. Proteinuria often is >10 mg/day. The disease occurs earlier and is of greater severity in males than in females. Dietary factors appear to have an important role in the progression of renal disease. Caloric restriction, the feeding of low-protein diets (4%–7%), and limiting the source of dietary protein reduce the incidence and severity of the disease. Treatment is supportive and involves feeding a low-protein diet.
Avascular necrosis of the tail, or ringtail, is seen primarily in young rats, and occasionally in young mice, kept in low-humidity environments. If ringtail is diagnosed, treatment involves amputation of the tail below the necrotic annular constriction.
Skin Disease in Mice:
Most of the diseases seen in pet mice are associated with the skin and represent >25% of all cases. Behavioral disorders, husbandry-related problems, microbiologic/parasitic infections, and idiopathic skin diseases are seen. Behavioral, husbandry-related, and infectious causes of skin disease are relatively straightforward to diagnose and treat. However, many skin diseases characterized by chronic or ulcerated skin (often secondarily colonized by bacteria) are diagnosed as idiopathic. This group is commonly unresponsive to treatment, topical or systemic, and affected mice are often euthanized.
Barbering and fighting are manifestations of social dominance, a form of behavior relating to the social rank and dominance status of an individual mouse in a group. Barbering is a unique condition seen in group-housed mice in which the dominant mouse nibbles off the whiskers and hair around the muzzle and eyes of cagemates. There are no other lesions, and only one mouse, the dominant individual, retains all of its fur. Removal of the dominant mouse stops barbering; frequently, however, another mouse assumes the dominant role. Barbering is often seen in female mice caged together. Male mice, except littermates raised together from birth, are more likely to fight, often very savagely, and inflict severe bite wounds on one another, especially over the rump, tail, and shoulders.
Mechanical abrasion resulting from self-trauma on cage equipment is a form of husbandry-related alopecia. Small patches of alopecia appear on the lateral surfaces of the muzzle. They result from chafing on metal feeders, poorly constructed watering device openings, and metal cage tops. Unlike barbering, dermatitis may also be associated with alopecia. Treatment consists of replacing the poorly constructed equipment with nonabrading equipment. Individually housed mice can display aberrant stereotypic behavior such as polydipsia and bar chewing that results in mechanical abrasion and alopecia. In these cases with one mouse, replacing the cage equipment does not help. Instead, environmental enrichment toys such as running wheels or hollow tubes should be provided. Nursing mice often have ventral abdominal and thoracic alopecia; this is normal and is nearly always associated with the extensive distribution of mammary glands.
Sometimes a pet mouse presents with clinical signs of mite infestation but no evidence of mites or known history of recent exposure to other animals. Biopsy samples may be useful in these cases to distinguish active acariasis from dermal hypersensitivity to mites or other allergens such as timber chip bedding. Dermal hypersensitivity is well described in certain inbred strains of mice and is characterized by severe pruritus, the presence of fine dandruff all over the body, and occasionally ulcerative dermatitis.
Idiopathic skin disease is characterized by ulcerative dermatitis with pruritus in mice that are negative for primary ectoparasitic, bacterial, or mycotic infections. Histopathologic examination and immunofluorescent microscopy of selected inbred strains of mice have revealed an underlying vasculitis attributed to immune complex deposition on dermal vessels. Dietary factors and dysregulated fatty acid metabolism have been implicated in the development of the ulcerative dermatitis in these mice. This common disease of mice of a C57BL6 background is caused by an underlying immune-mediated vasculitis, and the severity appears to be modulated by dietary fat and vitamin E content. Topical treatment twice daily with 0.2% cyclosporine in 2% lidocaine gel supplemented with gentamicin at 50 mcg/mL results in either complete healing or near-complete healing of the ulcerated skin, regardless of the size of the skin ulceration.
Skin swellings in mice are usually tumors or abscesses. Needle biopsy often reveals the nature of the contents and allows diagnosis. Three opportunistic pathogens, Staphylococcus aureus, Pasteurella pneumotropica, and Streptococcus pyogenes, are isolated frequently and can cause abscesses in other organs. Antibiotic therapy with penicillins or cephalosporins, concurrent with drainage and debridement of the abscess, is effective.
Chromodacryorrhea in Rats:
The Harderian glands of rats are located behind the eyes and secrete porphyrins that are increased in response to stress and disease, coloring the tears red. When porphyrin-enriched tear fluid dries around the eyes and external nares, it resembles crusts of blood. Owners often describe their rats as hemorrhaging from the eyes and nose. The porphyrins can be readily differentiated from blood with a Wood's lamp, because they fluoresce under ultraviolet light. Although chromodacryorrhea is not pathologic, it is a consequence of acute-onset stress such as that caused by pain, illness, or restraint. It usually indicates a chronic underlying disease.
As rats have become popular as pets, children now account for >50% of the cases of rat bite fever (RBF) in the USA; 14% of RBF cases in children involved exposure to a rat at school. RBF manifests as a bacteremia and septicemia characterized by fever, chills, myalgia, arthralgia, headache, and vomiting. A petechial rash develops over the extremities, in particular the palms and soles, but sometimes is present all over the body. The incubation period is 3–10 days (average 5 days). Infants and children may experience severe diarrhea resulting in weight loss. Mortality occurs in 7%–13% of untreated patients. After infection, a polyarthritis develops in 50%–70% of patients. Prognosis is good with treatment with parenteral penicillin early in the disease. Fatalities are associated with late reporting or late recognition of the disease. The nonspecific initial presentation combined with difficulties in culturing Streptococcus moniliformis produce a significant risk of delay or failure in diagnosis. Rats are not recommended as pets for children. Adults with pet rats should practice regular hand-washing and avoid hand-to-mouth contact when handling rats or cleaning rat cages.
There are sporadic but persistent reports of cases of Ornithonyssus bacoti dermatitis from pet rodents that manifests as an erythematous papular rash. It often excoriates because of intense pruritus. Occasionally, vesicles, urticarial plaques, diffuse erythema, or hemorrhage are seen. Affected areas of the skin are those usually covered by clothing (such as arms and trunk), with the face and webs of fingers usually spared. There is considerable evidence that O bacoti carry and have the potential to transmit several human pathogens. Experiments have shown that O bacoti transmits Rickettsia akari (rickettsialpox), Yersinia pestis (plague), Coxsackie virus, Francisella tularensis (tularemia), and Trypanosoma cruzi (Chagas' disease). Researchers have also documented O bacoti specimens with Coxiella burnetii (Q fever), hantavirus, Borrelia spp (Lyme disease), Bartonella spp, and Rickettsia spp.
Mice are inapparent carriers of dermatophytes, and pet mice are a zoonotic risk for their owners, especially children.
Disorders and Diseases of Rats
Diseases and Disorders of Mice
Introduction to Hamsters


text:
China's Tianwen-1 Spacecraft Arrives in Orbit of Mars
Mars from Hubble: Astronomers took advantage of a rare close approach by Mars in 2001. When the Red Planet was just 43 million miles away, Hubble snapped this picture with the WFPC2. It has a surface resolution of just 10 miles. This is the best image we've gotten of Mars that didn't involve sending a robot there.
Space around Mars is much busier than usual right now. The red planet made a close pass of Earth last summer, and numerous space agencies planned their Mars missions around this event. Now, the spacecraft are starting to show up — NASA's Perseverance rover will land later this month, and China's first Mars mission is already in orbit. The Tianwen-1 spacecraft arrived around Mars just this week, and it will land in the coming months not too far from NASA's latest rover.
China's Mars ambitions are not new. The country first partnered with Russia in the early 2010s to deliver a robotic explorer to the red planet. However, Russia's Fobos-Grunt vessel suffered an engine failure on liftoff, preventing it from escaping Earth's orbit. China's lander burned up in the atmosphere along with the rest of the Fobos-Grunt payload the following year. That failure spurred China to develop its own Mars program, and Tianwen-1 is the culmination of that.
China is looking to cover all its bases with Tianwen-1. The mission includes a stationary lander with a small rover that will explore the surface. There's also an orbiter component that will remain in space around Mars to keep an eye on the planet. The rover will land in a region called Utopia Planitia, just north of Jezero Crater where Perseverance will touch down on February 18th.
A model of the Tianwen-1 rover.
The Tianwen-1 robot is much smaller than Curiosity or Perseverance, and it uses solar panels for power instead of radioactive materials. It carries a surprising wealth of scientific instruments given its size. It has ground-penetrating radar to explore Martian strata up to 100 meters below the surface, and the Mars Surface Compound Detector will help the team search for evidence of past or present life on that planet.
China has yet to set a specific landing date, but it's targeting May 2021. Tianwen-1 also serves as a technology demonstration for a proposed Mars sample return mission the Chinese government wants to launch in the 2030s. While we have a handful of meteorites of Martian origin, they've been blasted free of their home planet and scorched in Earth's atmosphere on the way down. A pristine sample collected on Mars would be much more scientifically useful. NASA knows that, too. The Perseverance rover has a sample collection apparatus, but the mission to bring those samples back to Earth is still up in the air.
Now Read:
NASA Gives Up on InSight's Burrowing Mars Heat Probe
NASA Will Soon Have a Helicopter on Mars
The UAE Probe 'Hope' Has Successfully Reached Mars
Source From Extremetech
Author: Ryan Whitwam

redpajama_set_name: RedPajamaCommonCrawl


text:
"use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.createMessageConnection = exports.ConnectionOptions = exports.CancellationStrategy = exports.CancellationSenderStrategy = exports.CancellationReceiverStrategy = exports.ConnectionStrategy = exports.ConnectionError = exports.ConnectionErrors = exports.LogTraceNotification = exports.SetTraceNotification = exports.TraceFormat = exports.Trace = exports.NullLogger = exports.ProgressType = void 0;
const ral_1 = require("./ral");
const Is = require("./is");
const messages_1 = require("./messages");
const linkedMap_1 = require("./linkedMap");
const events_1 = require("./events");
const cancellation_1 = require("./cancellation");
var CancelNotification;
(function (CancelNotification) {
    CancelNotification.type = new messages_1.NotificationType('$/cancelRequest');
})(CancelNotification || (CancelNotification = {}));
var ProgressNotification;
(function (ProgressNotification) {
    ProgressNotification.type = new messages_1.NotificationType('$/progress');
})(ProgressNotification || (ProgressNotification = {}));
class ProgressType {
    constructor() {
    }
}
exports.ProgressType = ProgressType;
var StarRequestHandler;
(function (StarRequestHandler) {
    function is(value) {
        return Is.func(value);
    }
    StarRequestHandler.is = is;
})(StarRequestHandler || (StarRequestHandler = {}));
exports.NullLogger = Object.freeze({
    error: () => { },
    warn: () => { },
    info: () => { },
    log: () => { }
});
var Trace;
(function (Trace) {
    Trace[Trace["Off"] = 0] = "Off";
    Trace[Trace["Messages"] = 1] = "Messages";
    Trace[Trace["Verbose"] = 2] = "Verbose";
})(Trace = exports.Trace || (exports.Trace = {}));
(function (Trace) {
    function fromString(value) {
        if (!Is.string(value)) {
            return Trace.Off;
        }
        value = value.toLowerCase();
        switch (value) {
            case 'off':
                return Trace.Off;
            case 'messages':
                return Trace.Messages;
            case 'verbose':
                return Trace.Verbose;
            default:
                return Trace.Off;
        }
    }
    Trace.fromString = fromString;
    function toString(value) {
        switch (value) {
            case Trace.Off:
                return 'off';
            case Trace.Messages:
                return 'messages';
            case Trace.Verbose:
                return 'verbose';
            default:
                return 'off';
        }
    }
    Trace.toString = toString;
})(Trace = exports.Trace || (exports.Trace = {}));
var TraceFormat;
(function (TraceFormat) {
    TraceFormat["Text"] = "text";
    TraceFormat["JSON"] = "json";
})(TraceFormat = exports.TraceFormat || (exports.TraceFormat = {}));
(function (TraceFormat) {
    function fromString(value) {
        value = value.toLowerCase();
        if (value === 'json') {
            return TraceFormat.JSON;
        }
        else {
            return TraceFormat.Text;
        }
    }
    TraceFormat.fromString = fromString;
})(TraceFormat = exports.TraceFormat || (exports.TraceFormat = {}));
var SetTraceNotification;
(function (SetTraceNotification) {
    SetTraceNotification.type = new messages_1.NotificationType('$/setTrace');
})(SetTraceNotification = exports.SetTraceNotification || (exports.SetTraceNotification = {}));
var LogTraceNotification;
(function (LogTraceNotification) {
    LogTraceNotification.type = new messages_1.NotificationType('$/logTrace');
})(LogTraceNotification = exports.LogTraceNotification || (exports.LogTraceNotification = {}));
var ConnectionErrors;
(function (ConnectionErrors) {
    /**
     * The connection is closed.
     */
    ConnectionErrors[ConnectionErrors["Closed"] = 1] = "Closed";
    /**
     * The connection got disposed.
     */
    ConnectionErrors[ConnectionErrors["Disposed"] = 2] = "Disposed";
    /**
     * The connection is already in listening mode.
     */
    ConnectionErrors[ConnectionErrors["AlreadyListening"] = 3] = "AlreadyListening";
})(ConnectionErrors = exports.ConnectionErrors || (exports.ConnectionErrors = {}));
class ConnectionError extends Error {
    constructor(code, message) {
        super(message);
        this.code = code;
        Object.setPrototypeOf(this, ConnectionError.prototype);
    }
}
exports.ConnectionError = ConnectionError;
var ConnectionStrategy;
(function (ConnectionStrategy) {
    function is(value) {
        const candidate = value;
        return candidate && Is.func(candidate.cancelUndispatched);
    }
    ConnectionStrategy.is = is;
})(ConnectionStrategy = exports.ConnectionStrategy || (exports.ConnectionStrategy = {}));
var CancellationReceiverStrategy;
(function (CancellationReceiverStrategy) {
    CancellationReceiverStrategy.Message = Object.freeze({
        createCancellationTokenSource(_) {
            return new cancellation_1.CancellationTokenSource();
        }
    });
    function is(value) {
        const candidate = value;
        return candidate && Is.func(candidate.createCancellationTokenSource);
    }
    CancellationReceiverStrategy.is = is;
})(CancellationReceiverStrategy = exports.CancellationReceiverStrategy || (exports.CancellationReceiverStrategy = {}));
var CancellationSenderStrategy;
(function (CancellationSenderStrategy) {
    CancellationSenderStrategy.Message = Object.freeze({
        sendCancellation(conn, id) {
            conn.sendNotification(CancelNotification.type, { id });
        },
        cleanup(_) { }
    });
    function is(value) {
        const candidate = value;
        return candidate && Is.func(candidate.sendCancellation) && Is.func(candidate.cleanup);
    }
    CancellationSenderStrategy.is = is;
})(CancellationSenderStrategy = exports.CancellationSenderStrategy || (exports.CancellationSenderStrategy = {}));
var CancellationStrategy;
(function (CancellationStrategy) {
    CancellationStrategy.Message = Object.freeze({
        receiver: CancellationReceiverStrategy.Message,
        sender: CancellationSenderStrategy.Message
    });
    function is(value) {
        const candidate = value;
        return candidate && CancellationReceiverStrategy.is(candidate.receiver) && CancellationSenderStrategy.is(candidate.sender);
    }
    CancellationStrategy.is = is;
})(CancellationStrategy = exports.CancellationStrategy || (exports.CancellationStrategy = {}));
var ConnectionOptions;
(function (ConnectionOptions) {
    function is(value) {
        const candidate = value;
        return candidate && (CancellationStrategy.is(candidate.cancellationStrategy) || ConnectionStrategy.is(candidate.connectionStrategy));
    }
    ConnectionOptions.is = is;
})(ConnectionOptions = exports.ConnectionOptions || (exports.ConnectionOptions = {}));
var ConnectionState;
(function (ConnectionState) {
    ConnectionState[ConnectionState["New"] = 1] = "New";
    ConnectionState[ConnectionState["Listening"] = 2] = "Listening";
    ConnectionState[ConnectionState["Closed"] = 3] = "Closed";
    ConnectionState[ConnectionState["Disposed"] = 4] = "Disposed";
})(ConnectionState || (ConnectionState = {}));
function createMessageConnection(messageReader, messageWriter, _logger, options) {
    const logger = _logger !== undefined ? _logger : exports.NullLogger;
    let sequenceNumber = 0;
    let notificationSquenceNumber = 0;
    let unknownResponseSquenceNumber = 0;
    const version = '2.0';
    let starRequestHandler = undefined;
    const requestHandlers = Object.create(null);
    let starNotificationHandler = undefined;
    const notificationHandlers = Object.create(null);
    const progressHandlers = new Map();
    let timer;
    let messageQueue = new linkedMap_1.LinkedMap();
    let responsePromises = Object.create(null);
    let requestTokens = Object.create(null);
    let trace = Trace.Off;
    let traceFormat = TraceFormat.Text;
    let tracer;
    let state = ConnectionState.New;
    const errorEmitter = new events_1.Emitter();
    const closeEmitter = new events_1.Emitter();
    const unhandledNotificationEmitter = new events_1.Emitter();
    const unhandledProgressEmitter = new events_1.Emitter();
    const disposeEmitter = new events_1.Emitter();
    const cancellationStrategy = (options && options.cancellationStrategy) ? options.cancellationStrategy : CancellationStrategy.Message;
    function createRequestQueueKey(id) {
        if (id === null) {
            throw new Error(`Can't send requests with id null since the response can't be correlated.`);
        }
        return 'req-' + id.toString();
    }
    function createResponseQueueKey(id) {
        if (id === null) {
            return 'res-unknown-' + (++unknownResponseSquenceNumber).toString();
        }
        else {
            return 'res-' + id.toString();
        }
    }
    function createNotificationQueueKey() {
        return 'not-' + (++notificationSquenceNumber).toString();
    }
    function addMessageToQueue(queue, message) {
        if (messages_1.isRequestMessage(message)) {
            queue.set(createRequestQueueKey(message.id), message);
        }
        else if (messages_1.isResponseMessage(message)) {
            queue.set(createResponseQueueKey(message.id), message);
        }
        else {
            queue.set(createNotificationQueueKey(), message);
        }
    }
    function cancelUndispatched(_message) {
        return undefined;
    }
    function isListening() {
        return state === ConnectionState.Listening;
    }
    function isClosed() {
        return state === ConnectionState.Closed;
    }
    function isDisposed() {
        return state === ConnectionState.Disposed;
    }
    function closeHandler() {
        if (state === ConnectionState.New || state === ConnectionState.Listening) {
            state = ConnectionState.Closed;
            closeEmitter.fire(undefined);
        }
        // If the connection is disposed don't sent close events.
    }
    function readErrorHandler(error) {
        errorEmitter.fire([error, undefined, undefined]);
    }
    function writeErrorHandler(data) {
        errorEmitter.fire(data);
    }
    messageReader.onClose(closeHandler);
    messageReader.onError(readErrorHandler);
    messageWriter.onClose(closeHandler);
    messageWriter.onError(writeErrorHandler);
    function triggerMessageQueue() {
        if (timer || messageQueue.size === 0) {
            return;
        }
        timer = ral_1.default().timer.setImmediate(() => {
            timer = undefined;
            processMessageQueue();
        });
    }
    function processMessageQueue() {
        if (messageQueue.size === 0) {
            return;
        }
        const message = messageQueue.shift();
        try {
            if (messages_1.isRequestMessage(message)) {
                handleRequest(message);
            }
            else if (messages_1.isNotificationMessage(message)) {
                handleNotification(message);
            }
            else if (messages_1.isResponseMessage(message)) {
                handleResponse(message);
            }
            else {
                handleInvalidMessage(message);
            }
        }
        finally {
            triggerMessageQueue();
        }
    }
    const callback = (message) => {
        try {
            // We have received a cancellation message. Check if the message is still in the queue
            // and cancel it if allowed to do so.
            if (messages_1.isNotificationMessage(message) && message.method === CancelNotification.type.method) {
                const key = createRequestQueueKey(message.params.id);
                const toCancel = messageQueue.get(key);
                if (messages_1.isRequestMessage(toCancel)) {
                    const strategy = options === null || options === void 0 ? void 0 : options.connectionStrategy;
                    const response = (strategy && strategy.cancelUndispatched) ? strategy.cancelUndispatched(toCancel, cancelUndispatched) : cancelUndispatched(toCancel);
                    if (response && (response.error !== undefined || response.result !== undefined)) {
                        messageQueue.delete(key);
                        response.id = toCancel.id;
                        traceSendingResponse(response, message.method, Date.now());
                        messageWriter.write(response);
                        return;
                    }
                }
            }
            addMessageToQueue(messageQueue, message);
        }
        finally {
            triggerMessageQueue();
        }
    };
    function handleRequest(requestMessage) {
        if (isDisposed()) {
            // we return here silently since we fired an event when the
            // connection got disposed.
            return;
        }
        function reply(resultOrError, method, startTime) {
            const message = {
                jsonrpc: version,
                id: requestMessage.id
            };
            if (resultOrError instanceof messages_1.ResponseError) {
                message.error = resultOrError.toJson();
            }
            else {
                message.result = resultOrError === undefined ? null : resultOrError;
            }
            traceSendingResponse(message, method, startTime);
            messageWriter.write(message);
        }
        function replyError(error, method, startTime) {
            const message = {
                jsonrpc: version,
                id: requestMessage.id,
                error: error.toJson()
            };
            traceSendingResponse(message, method, startTime);
            messageWriter.write(message);
        }
        function replySuccess(result, method, startTime) {
            // The JSON RPC defines that a response must either have a result or an error
            // So we can't treat undefined as a valid response result.
            if (result === undefined) {
                result = null;
            }
            const message = {
                jsonrpc: version,
                id: requestMessage.id,
                result: result
            };
            traceSendingResponse(message, method, startTime);
            messageWriter.write(message);
        }
        traceReceivedRequest(requestMessage);
        const element = requestHandlers[requestMessage.method];
        let type;
        let requestHandler;
        if (element) {
            type = element.type;
            requestHandler = element.handler;
        }
        const startTime = Date.now();
        if (requestHandler || starRequestHandler) {
            const tokenKey = String(requestMessage.id);
            const cancellationSource = cancellationStrategy.receiver.createCancellationTokenSource(tokenKey);
            requestTokens[tokenKey] = cancellationSource;
            try {
                let handlerResult;
                if (requestHandler) {
                    if (requestMessage.params === undefined) {
                        if (type !== undefined && type.numberOfParams !== 0) {
                            replyError(new messages_1.ResponseError(messages_1.ErrorCodes.InvalidParams, `Request ${requestMessage.method} defines ${type.numberOfParams} params but recevied none.`), requestMessage.method, startTime);
                            return;
                        }
                        handlerResult = requestHandler(cancellationSource.token);
                    }
                    else if (Array.isArray(requestMessage.params)) {
                        if (type !== undefined && type.parameterStructures === messages_1.ParameterStructures.byName) {
                            replyError(new messages_1.ResponseError(messages_1.ErrorCodes.InvalidParams, `Request ${requestMessage.method} defines parameters by name but received parameters by position`), requestMessage.method, startTime);
                            return;
                        }
                        handlerResult = requestHandler(...requestMessage.params, cancellationSource.token);
                    }
                    else {
                        if (type !== undefined && type.parameterStructures === messages_1.ParameterStructures.byPosition) {
                            replyError(new messages_1.ResponseError(messages_1.ErrorCodes.InvalidParams, `Request ${requestMessage.method} defines parameters by position but received parameters by name`), requestMessage.method, startTime);
                            return;
                        }
                        handlerResult = requestHandler(requestMessage.params, cancellationSource.token);
                    }
                }
                else if (starRequestHandler) {
                    handlerResult = starRequestHandler(requestMessage.method, requestMessage.params, cancellationSource.token);
                }
                const promise = handlerResult;
                if (!handlerResult) {
                    delete requestTokens[tokenKey];
                    replySuccess(handlerResult, requestMessage.method, startTime);
                }
                else if (promise.then) {
                    promise.then((resultOrError) => {
                        delete requestTokens[tokenKey];
                        reply(resultOrError, requestMessage.method, startTime);
                    }, error => {
                        delete requestTokens[tokenKey];
                        if (error instanceof messages_1.ResponseError) {
                            replyError(error, requestMessage.method, startTime);
                        }
                        else if (error && Is.string(error.message)) {
                            replyError(new messages_1.ResponseError(messages_1.ErrorCodes.InternalError, `Request ${requestMessage.method} failed with message: ${error.message}`), requestMessage.method, startTime);
                        }
                        else {
                            replyError(new messages_1.ResponseError(messages_1.ErrorCodes.InternalError, `Request ${requestMessage.method} failed unexpectedly without providing any details.`), requestMessage.method, startTime);
                        }
                    });
                }
                else {
                    delete requestTokens[tokenKey];
                    reply(handlerResult, requestMessage.method, startTime);
                }
            }
            catch (error) {
                delete requestTokens[tokenKey];
                if (error instanceof messages_1.ResponseError) {
                    reply(error, requestMessage.method, startTime);
                }
                else if (error && Is.string(error.message)) {
                    replyError(new messages_1.ResponseError(messages_1.ErrorCodes.InternalError, `Request ${requestMessage.method} failed with message: ${error.message}`), requestMessage.method, startTime);
                }
                else {
                    replyError(new messages_1.ResponseError(messages_1.ErrorCodes.InternalError, `Request ${requestMessage.method} failed unexpectedly without providing any details.`), requestMessage.method, startTime);
                }
            }
        }
        else {
            replyError(new messages_1.ResponseError(messages_1.ErrorCodes.MethodNotFound, `Unhandled method ${requestMessage.method}`), requestMessage.method, startTime);
        }
    }
    function handleResponse(responseMessage) {
        if (isDisposed()) {
            // See handle request.
            return;
        }
        if (responseMessage.id === null) {
            if (responseMessage.error) {
                logger.error(`Received response message without id: Error is: \n${JSON.stringify(responseMessage.error, undefined, 4)}`);
            }
            else {
                logger.error(`Received response message without id. No further error information provided.`);
            }
        }
        else {
            const key = String(responseMessage.id);
            const responsePromise = responsePromises[key];
            traceReceivedResponse(responseMessage, responsePromise);
            if (responsePromise) {
                delete responsePromises[key];
                try {
                    if (responseMessage.error) {
                        const error = responseMessage.error;
                        responsePromise.reject(new messages_1.ResponseError(error.code, error.message, error.data));
                    }
                    else if (responseMessage.result !== undefined) {
                        responsePromise.resolve(responseMessage.result);
                    }
                    else {
                        throw new Error('Should never happen.');
                    }
                }
                catch (error) {
                    if (error.message) {
                        logger.error(`Response handler '${responsePromise.method}' failed with message: ${error.message}`);
                    }
                    else {
                        logger.error(`Response handler '${responsePromise.method}' failed unexpectedly.`);
                    }
                }
            }
        }
    }
    function handleNotification(message) {
        if (isDisposed()) {
            // See handle request.
            return;
        }
        let type = undefined;
        let notificationHandler;
        if (message.method === CancelNotification.type.method) {
            notificationHandler = (params) => {
                const id = params.id;
                const source = requestTokens[String(id)];
                if (source) {
                    source.cancel();
                }
            };
        }
        else {
            const element = notificationHandlers[message.method];
            if (element) {
                notificationHandler = element.handler;
                type = element.type;
            }
        }
        if (notificationHandler || starNotificationHandler) {
            try {
                traceReceivedNotification(message);
                if (notificationHandler) {
                    if (message.params === undefined) {
                        if (type !== undefined) {
                            if (type.numberOfParams !== 0 && type.parameterStructures !== messages_1.ParameterStructures.byName) {
                                logger.error(`Notification ${message.method} defines ${type.numberOfParams} params but recevied none.`);
                            }
                        }
                        notificationHandler();
                    }
                    else if (Array.isArray(message.params)) {
                        if (type !== undefined) {
                            if (type.parameterStructures === messages_1.ParameterStructures.byName) {
                                logger.error(`Notification ${message.method} defines parameters by name but received parameters by position`);
                            }
                            if (type.numberOfParams !== message.params.length) {
                                logger.error(`Notification ${message.method} defines ${type.numberOfParams} params but received ${message.params.length} argumennts`);
                            }
                        }
                        notificationHandler(...message.params);
                    }
                    else {
                        if (type !== undefined && type.parameterStructures === messages_1.ParameterStructures.byPosition) {
                            logger.error(`Notification ${message.method} defines parameters by position but received parameters by name`);
                        }
                        notificationHandler(message.params);
                    }
                }
                else if (starNotificationHandler) {
                    starNotificationHandler(message.method, message.params);
                }
            }
            catch (error) {
                if (error.message) {
                    logger.error(`Notification handler '${message.method}' failed with message: ${error.message}`);
                }
                else {
                    logger.error(`Notification handler '${message.method}' failed unexpectedly.`);
                }
            }
        }
        else {
            unhandledNotificationEmitter.fire(message);
        }
    }
    function handleInvalidMessage(message) {
        if (!message) {
            logger.error('Received empty message.');
            return;
        }
        logger.error(`Received message which is neither a response nor a notification message:\n${JSON.stringify(message, null, 4)}`);
        // Test whether we find an id to reject the promise
        const responseMessage = message;
        if (Is.string(responseMessage.id) || Is.number(responseMessage.id)) {
            const key = String(responseMessage.id);
            const responseHandler = responsePromises[key];
            if (responseHandler) {
                responseHandler.reject(new Error('The received response has neither a result nor an error property.'));
            }
        }
    }
    function traceSendingRequest(message) {
        if (trace === Trace.Off || !tracer) {
            return;
        }
        if (traceFormat === TraceFormat.Text) {
            let data = undefined;
            if (trace === Trace.Verbose && message.params) {
                data = `Params: ${JSON.stringify(message.params, null, 4)}\n\n`;
            }
            tracer.log(`Sending request '${message.method} - (${message.id})'.`, data);
        }
        else {
            logLSPMessage('send-request', message);
        }
    }
    function traceSendingNotification(message) {
        if (trace === Trace.Off || !tracer) {
            return;
        }
        if (traceFormat === TraceFormat.Text) {
            let data = undefined;
            if (trace === Trace.Verbose) {
                if (message.params) {
                    data = `Params: ${JSON.stringify(message.params, null, 4)}\n\n`;
                }
                else {
                    data = 'No parameters provided.\n\n';
                }
            }
            tracer.log(`Sending notification '${message.method}'.`, data);
        }
        else {
            logLSPMessage('send-notification', message);
        }
    }
    function traceSendingResponse(message, method, startTime) {
        if (trace === Trace.Off || !tracer) {
            return;
        }
        if (traceFormat === TraceFormat.Text) {
            let data = undefined;
            if (trace === Trace.Verbose) {
                if (message.error && message.error.data) {
                    data = `Error data: ${JSON.stringify(message.error.data, null, 4)}\n\n`;
                }
                else {
                    if (message.result) {
                        data = `Result: ${JSON.stringify(message.result, null, 4)}\n\n`;
                    }
                    else if (message.error === undefined) {
                        data = 'No result returned.\n\n';
                    }
                }
            }
            tracer.log(`Sending response '${method} - (${message.id})'. Processing request took ${Date.now() - startTime}ms`, data);
        }
        else {
            logLSPMessage('send-response', message);
        }
    }
    function traceReceivedRequest(message) {
        if (trace === Trace.Off || !tracer) {
            return;
        }
        if (traceFormat === TraceFormat.Text) {
            let data = undefined;
            if (trace === Trace.Verbose && message.params) {
                data = `Params: ${JSON.stringify(message.params, null, 4)}\n\n`;
            }
            tracer.log(`Received request '${message.method} - (${message.id})'.`, data);
        }
        else {
            logLSPMessage('receive-request', message);
        }
    }
    function traceReceivedNotification(message) {
        if (trace === Trace.Off || !tracer || message.method === LogTraceNotification.type.method) {
            return;
        }
        if (traceFormat === TraceFormat.Text) {
            let data = undefined;
            if (trace === Trace.Verbose) {
                if (message.params) {
                    data = `Params: ${JSON.stringify(message.params, null, 4)}\n\n`;
                }
                else {
                    data = 'No parameters provided.\n\n';
                }
            }
            tracer.log(`Received notification '${message.method}'.`, data);
        }
        else {
            logLSPMessage('receive-notification', message);
        }
    }
    function traceReceivedResponse(message, responsePromise) {
        if (trace === Trace.Off || !tracer) {
            return;
        }
        if (traceFormat === TraceFormat.Text) {
            let data = undefined;
            if (trace === Trace.Verbose) {
                if (message.error && message.error.data) {
                    data = `Error data: ${JSON.stringify(message.error.data, null, 4)}\n\n`;
                }
                else {
                    if (message.result) {
                        data = `Result: ${JSON.stringify(message.result, null, 4)}\n\n`;
                    }
                    else if (message.error === undefined) {
                        data = 'No result returned.\n\n';
                    }
                }
            }
            if (responsePromise) {
                const error = message.error ? ` Request failed: ${message.error.message} (${message.error.code}).` : '';
                tracer.log(`Received response '${responsePromise.method} - (${message.id})' in ${Date.now() - responsePromise.timerStart}ms.${error}`, data);
            }
            else {
                tracer.log(`Received response ${message.id} without active response promise.`, data);
            }
        }
        else {
            logLSPMessage('receive-response', message);
        }
    }
    function logLSPMessage(type, message) {
        if (!tracer || trace === Trace.Off) {
            return;
        }
        const lspMessage = {
            isLSPMessage: true,
            type,
            message,
            timestamp: Date.now()
        };
        tracer.log(lspMessage);
    }
    function throwIfClosedOrDisposed() {
        if (isClosed()) {
            throw new ConnectionError(ConnectionErrors.Closed, 'Connection is closed.');
        }
        if (isDisposed()) {
            throw new ConnectionError(ConnectionErrors.Disposed, 'Connection is disposed.');
        }
    }
    function throwIfListening() {
        if (isListening()) {
            throw new ConnectionError(ConnectionErrors.AlreadyListening, 'Connection is already listening');
        }
    }
    function throwIfNotListening() {
        if (!isListening()) {
            throw new Error('Call listen() first.');
        }
    }
    function undefinedToNull(param) {
        if (param === undefined) {
            return null;
        }
        else {
            return param;
        }
    }
    function nullToUndefined(param) {
        if (param === null) {
            return undefined;
        }
        else {
            return param;
        }
    }
    function isNamedParam(param) {
        return param !== undefined && param !== null && !Array.isArray(param) && typeof param === 'object';
    }
    function computeSingleParam(parameterStructures, param) {
        switch (parameterStructures) {
            case messages_1.ParameterStructures.auto:
                if (isNamedParam(param)) {
                    return nullToUndefined(param);
                }
                else {
                    return [undefinedToNull(param)];
                }
                break;
            case messages_1.ParameterStructures.byName:
                if (!isNamedParam(param)) {
                    throw new Error(`Recevied parameters by name but param is not an object literal.`);
                }
                return nullToUndefined(param);
            case messages_1.ParameterStructures.byPosition:
                return [undefinedToNull(param)];
            default:
                throw new Error(`Unknown parameter structure ${parameterStructures.toString()}`);
        }
    }
    function computeMessageParams(type, params) {
        let result;
        const numberOfParams = type.numberOfParams;
        switch (numberOfParams) {
            case 0:
                result = undefined;
                break;
            case 1:
                result = computeSingleParam(type.parameterStructures, params[0]);
                break;
            default:
                result = [];
                for (let i = 0; i < params.length && i < numberOfParams; i++) {
                    result.push(undefinedToNull(params[i]));
                }
                if (params.length < numberOfParams) {
                    for (let i = params.length; i < numberOfParams; i++) {
                        result.push(null);
                    }
                }
                break;
        }
        return result;
    }
    const connection = {
        sendNotification: (type, ...args) => {
            throwIfClosedOrDisposed();
            let method;
            let messageParams;
            if (Is.string(type)) {
                method = type;
                const first = args[0];
                let paramStart = 0;
                let parameterStructures = messages_1.ParameterStructures.auto;
                if (messages_1.ParameterStructures.is(first)) {
                    paramStart = 1;
                    parameterStructures = first;
                }
                let paramEnd = args.length;
                const numberOfParams = paramEnd - paramStart;
                switch (numberOfParams) {
                    case 0:
                        messageParams = undefined;
                        break;
                    case 1:
                        messageParams = computeSingleParam(parameterStructures, args[paramStart]);
                        break;
                    default:
                        if (parameterStructures === messages_1.ParameterStructures.byName) {
                            throw new Error(`Recevied ${numberOfParams} parameters for 'by Name' notification parameter structure.`);
                        }
                        messageParams = args.slice(paramStart, paramEnd).map(value => undefinedToNull(value));
                        break;
                }
            }
            else {
                const params = args;
                method = type.method;
                messageParams = computeMessageParams(type, params);
            }
            const notificationMessage = {
                jsonrpc: version,
                method: method,
                params: messageParams
            };
            traceSendingNotification(notificationMessage);
            messageWriter.write(notificationMessage);
        },
        onNotification: (type, handler) => {
            throwIfClosedOrDisposed();
            let method;
            if (Is.func(type)) {
                starNotificationHandler = type;
            }
            else if (handler) {
                if (Is.string(type)) {
                    method = type;
                    notificationHandlers[type] = { type: undefined, handler };
                }
                else {
                    method = type.method;
                    notificationHandlers[type.method] = { type, handler };
                }
            }
            return {
                dispose: () => {
                    if (method !== undefined) {
                        delete notificationHandlers[method];
                    }
                    else {
                        starNotificationHandler = undefined;
                    }
                }
            };
        },
        onProgress: (_type, token, handler) => {
            if (progressHandlers.has(token)) {
                throw new Error(`Progress handler for token ${token} already registered`);
            }
            progressHandlers.set(token, handler);
            return {
                dispose: () => {
                    progressHandlers.delete(token);
                }
            };
        },
        sendProgress: (_type, token, value) => {
            connection.sendNotification(ProgressNotification.type, { token, value });
        },
        onUnhandledProgress: unhandledProgressEmitter.event,
        sendRequest: (type, ...args) => {
            throwIfClosedOrDisposed();
            throwIfNotListening();
            let method;
            let messageParams;
            let token = undefined;
            if (Is.string(type)) {
                method = type;
                const first = args[0];
                const last = args[args.length - 1];
                let paramStart = 0;
                let parameterStructures = messages_1.ParameterStructures.auto;
                if (messages_1.ParameterStructures.is(first)) {
                    paramStart = 1;
                    parameterStructures = first;
                }
                let paramEnd = args.length;
                if (cancellation_1.CancellationToken.is(last)) {
                    paramEnd = paramEnd - 1;
                    token = last;
                }
                const numberOfParams = paramEnd - paramStart;
                switch (numberOfParams) {
                    case 0:
                        messageParams = undefined;
                        break;
                    case 1:
                        messageParams = computeSingleParam(parameterStructures, args[paramStart]);
                        break;
                    default:
                        if (parameterStructures === messages_1.ParameterStructures.byName) {
                            throw new Error(`Recevied ${numberOfParams} parameters for 'by Name' request parameter structure.`);
                        }
                        messageParams = args.slice(paramStart, paramEnd).map(value => undefinedToNull(value));
                        break;
                }
            }
            else {
                const params = args;
                method = type.method;
                messageParams = computeMessageParams(type, params);
                const numberOfParams = type.numberOfParams;
                token = cancellation_1.CancellationToken.is(params[numberOfParams]) ? params[numberOfParams] : undefined;
            }
            const id = sequenceNumber++;
            let disposable;
            if (token) {
                disposable = token.onCancellationRequested(() => {
                    cancellationStrategy.sender.sendCancellation(connection, id);
                });
            }
            const result = new Promise((resolve, reject) => {
                const requestMessage = {
                    jsonrpc: version,
                    id: id,
                    method: method,
                    params: messageParams
                };
                const resolveWithCleanup = (r) => {
                    resolve(r);
                    cancellationStrategy.sender.cleanup(id);
                    disposable === null || disposable === void 0 ? void 0 : disposable.dispose();
                };
                const rejectWithCleanup = (r) => {
                    reject(r);
                    cancellationStrategy.sender.cleanup(id);
                    disposable === null || disposable === void 0 ? void 0 : disposable.dispose();
                };
                let responsePromise = { method: method, timerStart: Date.now(), resolve: resolveWithCleanup, reject: rejectWithCleanup };
                traceSendingRequest(requestMessage);
                try {
                    messageWriter.write(requestMessage);
                }
                catch (e) {
                    // Writing the message failed. So we need to reject the promise.
                    responsePromise.reject(new messages_1.ResponseError(messages_1.ErrorCodes.MessageWriteError, e.message ? e.message : 'Unknown reason'));
                    responsePromise = null;
                }
                if (responsePromise) {
                    responsePromises[String(id)] = responsePromise;
                }
            });
            return result;
        },
        onRequest: (type, handler) => {
            throwIfClosedOrDisposed();
            let method = null;
            if (StarRequestHandler.is(type)) {
                method = undefined;
                starRequestHandler = type;
            }
            else if (Is.string(type)) {
                method = null;
                if (handler !== undefined) {
                    method = type;
                    requestHandlers[type] = { handler: handler, type: undefined };
                }
            }
            else {
                if (handler !== undefined) {
                    method = type.method;
                    requestHandlers[type.method] = { type, handler };
                }
            }
            return {
                dispose: () => {
                    if (method === null) {
                        return;
                    }
                    if (method !== undefined) {
                        delete requestHandlers[method];
                    }
                    else {
                        starRequestHandler = undefined;
                    }
                }
            };
        },
        trace: (_value, _tracer, sendNotificationOrTraceOptions) => {
            let _sendNotification = false;
            let _traceFormat = TraceFormat.Text;
            if (sendNotificationOrTraceOptions !== undefined) {
                if (Is.boolean(sendNotificationOrTraceOptions)) {
                    _sendNotification = sendNotificationOrTraceOptions;
                }
                else {
                    _sendNotification = sendNotificationOrTraceOptions.sendNotification || false;
                    _traceFormat = sendNotificationOrTraceOptions.traceFormat || TraceFormat.Text;
                }
            }
            trace = _value;
            traceFormat = _traceFormat;
            if (trace === Trace.Off) {
                tracer = undefined;
            }
            else {
                tracer = _tracer;
            }
            if (_sendNotification && !isClosed() && !isDisposed()) {
                connection.sendNotification(SetTraceNotification.type, { value: Trace.toString(_value) });
            }
        },
        onError: errorEmitter.event,
        onClose: closeEmitter.event,
        onUnhandledNotification: unhandledNotificationEmitter.event,
        onDispose: disposeEmitter.event,
        end: () => {
            messageWriter.end();
        },
        dispose: () => {
            if (isDisposed()) {
                return;
            }
            state = ConnectionState.Disposed;
            disposeEmitter.fire(undefined);
            const error = new Error('Connection got disposed.');
            Object.keys(responsePromises).forEach((key) => {
                responsePromises[key].reject(error);
            });
            responsePromises = Object.create(null);
            requestTokens = Object.create(null);
            messageQueue = new linkedMap_1.LinkedMap();
            // Test for backwards compatibility
            if (Is.func(messageWriter.dispose)) {
                messageWriter.dispose();
            }
            if (Is.func(messageReader.dispose)) {
                messageReader.dispose();
            }
        },
        listen: () => {
            throwIfClosedOrDisposed();
            throwIfListening();
            state = ConnectionState.Listening;
            messageReader.listen(callback);
        },
        inspect: () => {
            // eslint-disable-next-line no-console
            ral_1.default().console.log('inspect');
        }
    };
    connection.onNotification(LogTraceNotification.type, (params) => {
        if (trace === Trace.Off || !tracer) {
            return;
        }
        tracer.log(params.message, trace === Trace.Verbose ? params.verbose : undefined);
    });
    connection.onNotification(ProgressNotification.type, (params) => {
        const handler = progressHandlers.get(params.token);
        if (handler) {
            handler(params.value);
        }
        else {
            unhandledProgressEmitter.fire(params);
        }
    });
    return connection;
}
exports.createMessageConnection = createMessageConnection;
//# sourceMappingURL=connection.js.map

redpajama_set_name: RedPajamaGithub


text:
Rihanna has a regret about this outfit...
March 18, 2016 - 14:28 GMT hellomagazine.com We weren't expecting that.
Jaws dropped when Rihanna stepped out at the CDFA Awards back in 2014 sporting an almost completely sheer dress that showed off every inch of her incredible curves.
Custom-made for the star by designer Adam Selman, the dress comprised of a total of 216,000 Swarovski crystals.
But while Rihanna hit headlines the world over for the daring look, she has just revealed that she has one regret about the look...
Rihanna turned heads with the racy look
During her interview with Vogue, the megastar was asked about her decision to wear the dress and whether she had any regrets about the look.
We love her response: "I just liked it better without the lines underneath. Could you imagine the CFDA dress with a bra? I would slice my throat.
"I already wanted to, for wearing a thong that wasn't bedazzled. That's the only regret I have in life."
The star revealed she has a regret about the dress
Asked to clarify that wearing a thong that wasn't bedazzled is the greatest regret in her life, Rihanna replied: "To the CFDA awards. Yes."
In the interview, Rihanna also touched upon rumours that she has a feud with fellow popstar Beyoncé.
"Here's the deal," she said. "They just get so excited to feast on something that's negative. Something that's competitive. Something that's, you know, a rivalry. And that's just not what I wake up to. Because I can only do me. And nobody else is going to be able to do that."
More about fashion news
The iconic accessory the Queen is never without on rainy days
Kendall Jenner shows off Giambattista Valli's H&M Collection - and here's when it launches
This is this season's most searched-for fashion accessory - and you might already own it
Anna Wintour's Met Gala demands revealed
Dior announces collaboration with Rihanna
Rihanna has designed sunglasses - and they're pretty cool
Emma Stone has revealed her biggest beauty regret


The world of Heineken is a world of quality and authenticity. Its traditional elaboration has produced an exceptional taste, aroma, colour and clarity for more then 135 years. An achievement reached through being true to their values.
This interactive advertising campaign intends to capture that philosophy. Heineken are not following any other rules then their own. Their focus is as original as it is personal and they want to share it with you.